赞
踩
在本文中,您将学习如何构建一个 GitHub 跟踪器,当跟踪的存储库中有新的问题/PR 时,它会通过发送推送通知来通知用户。
如果您选择加入,GitHub 已经通过电子邮件发送通知,但许多研究表明,推送通知比电子邮件更能吸引用户。按照本教程构建 GitHub 跟踪器后,您将学会如何:
阅读本文需要一些技能和服务:
让我们来看看这些所谓的“推送通知”是什么。
您必须熟悉定期通知。这些是出现在屏幕上的小气泡文本,用于通知您某些事情。推送通知类似,只是它们不是按需生成的,而是在接收推送事件时生成的。推送通知在应用程序关闭时起作用,而常规通知要求您打开应用程序。
现代 Web 浏览器(如 Chrome)通过使用称为服务工作者的东西支持推送通知。Service Worker 是独立于浏览器主线程运行的一小段 JavaScript,因此,如果您的应用程序安装为 PWA(渐进式 Web 应用程序),则可以离线运行。
推送通知用于聊天应用程序中以在用户有未读消息时通知用户,在游戏中,通知用户游戏事件,在新闻站点中,通知用户突发文章,以及用于许多其他目的。
在您的应用程序中显示推送通知有四个步骤:
让我们在本文中使用 Svelte 和Vite.js,而不是 Rollup。顾名思义,Vite 比 Rollup 更快,并且还提供了对环境变量的内置支持。要使用 Svelte 和 Vite 创建新项目,请运行以下命令:
npm init vite
选择要成为的框架svelte。如果你愿意,你可以使用 TypeScript。我将使用常规的 JavaScript。
接下来,cd进入项目文件夹,您可以将TailwindCSS添加到您的应用程序并使用以下命令安装所有依赖项:
- npx svelte-add tailwindcss
-
- # Install packages
- yarn install # or npm install
最后,在您喜欢的代码编辑器中打开项目并在http://localhost:3000npm run dev上运行或yarn dev启动应用程序。
我们将使用 GitHub API 获取用户跟踪的存储库的问题列表和拉取请求。用户跟踪的存储库及其用户名将存储在 MongoDB 数据库中。
第一步是提示用户输入他们的用户名。Create
src/lib/UsernamePrompt.svelte,它将是执行此操作的组件。这是我的表单 UI,但您可以根据需要进行设计:
- <script>
- let username = "";
- async function submit() {
- // TODO
- }
- </script>
-
- <form
- on:submit|preventDefault="{submit}"
- class="mx-auto min-w-[350px] max-w-[1100px] w-[50%] border border-gray-500 rounded my-4 px-6 py-4"
- >
- <h1 class="text-center text-3xl m-4">Enter a username</h1>
- <p class="text-center text-xl m-4">Enter a username to use this tracker</p>
-
- <input
- type="text"
- class="rounded px-4 py-2 border border-gray-300 w-full outline-none"
- placeholder="Username"
- aria-label="Username"
- bind:value="{username}"
- />
-
- <button
- class="mt-4 border border-transparent bg-blue-500 text-white rounded px-4 py-2 w-full"
- >
- Submit
- </button>
- </form>
像这样添加这个组件App.svelte:
- <script>
- import UsernamePrompt from "./lib/UsernamePrompt.svelte";
- </script>
-
- <UsernamePrompt />
接下来,让我们添加主动跟踪器 UI。创建文件src/lib/Tracker.svelte并在其中添加以下代码:
- <script>
- let repo = "";
- function track() {
- // TODO
- }
-
- function untrack(repo) {
- // TODO
- }
- </script>
-
- <form
- on:submit|preventDefault={track}
- class="mx-auto min-w-[350px] max-w-[1100px] w-[50%] border border-gray-500 rounded my-4 px-6 py-4"
- >
- <h1 class="text-center text-3xl m-4">GitHub tracker</h1>
-
- <input
- type="text"
- class="rounded px-4 py-2 border border-gray-300 w-full outline-none"
- placeholder="Enter the repository's URL"
- aria-label="Repository URL"
- bind:value={repo}
- />
- <button
- class="mt-2 border border-transparent bg-blue-500 text-white rounded px-4 py-2 w-full"
- >Track repository</button
- >
-
- <h2 class="mt-4 text-2xl">Tracked repositories</h2>
- <ul class="m-2 list-decimal">
- <!-- We'll use a loop to automatically add repositories here later on. -->
- <li class="py-1 flex items-center justify-between">
- <a class="text-gray-500 hover:underline" href="https://github.com/test/test"
- >https://github.com/test/test</a
- >
- <button class="text-red-500 cursor-pointer" on:click={() => untrack("")}
- >Untrack</button
- >
- </li>
- </ul>
- </form>
要测试您的组件,请暂时将组件换成UsernamePrompt新Tracker组件App.svelte:
- <script>
- // import UsernamePrompt from "./lib/UsernamePrompt.svelte";
- import Tracker from "./lib/Tracker.svelte";
- </script>
-
- <!-- <UsernamePrompt /> -->
- <Tracker />
您的屏幕现在应该如下所示:
注意:记得恢复App.svelte到之前的代码!
我们需要有一个后端服务器来向我们的应用程序发送推送事件。这意味着您需要创建一个新的(可能)ExpressJS 项目,然后单独部署它。对于刚刚尝试推送通知的人来说,这将是一件令人头疼的事情。
Vercel 云函数来救援!云功能就像 Express 路由。他们可以运行代码并在您获取其 URL 时给您响应。Vercel 支持云功能;您只需要在api文件夹中创建文件。您将使用云功能与 MongoDB 进行交互,因为在客户端公开秘密从来都不是一件好事。
首先,确保您在MongoDB Atlas中有一个集群。MongoDB 有一个免费计划 ( M0),所以如果您还没有,请务必创建一个。现在,转到Atlas 仪表板侧栏中的Database Access选项卡。通过单击右侧的绿色按钮添加新的数据库用户。输入用户的详细信息(不要忘记密码),然后创建用户。
要连接到数据库,您需要连接字符串。将新用户和密码保存在某处,然后前往集群概览。单击右侧的连接按钮,然后选择连接您的应用程序作为连接方法。您应该看到一个类似于下面的连接字符串。
现在您有了连接字符串,您可以连接到数据库,但首先,您需要将当前应用程序部署到Vercel。最简单的方法是使用GitHub。
创建一个新的GitHub 存储库并将您的代码推送到其中。接下来,前往您的Vercel 仪表板并单击“新建项目”按钮。导入您的 GitHub 存储库,确保框架为Vite,并添加一个名为MONGODB_URL. 将其值设置为 MongoDB 数据库的连接字符串。
部署网站后,您需要将本地开发命令从 更改yarn dev为vercel dev. 运行命令后,如果系统要求您链接到现有项目,请单击yes。
npm i -g vercel注意:如果您还没有安装 Vercel CLI,请确保安装。
vite像我一样,如果您在使用with时遇到问题vercel dev,请务必将项目的Development Command更改为Vercel Dashboardvite --port $PORT中的from 。vite
这将允许我们在本地使用具有正确环境变量的云函数。
让我们添加一个帮助文件,它允许我们在不打开太多连接的情况下访问 MongoDB。创建文件api/_mongo.js并将以下代码放入其中。api目录中以 a 为前缀的文件_不会被视为云函数。这允许我们在单独的文件中添加助手和其他逻辑:
- const { MongoClient } = require("mongodb");
-
- const mongo = new MongoClient(process.env.MONGODB_URL);
-
- // Export the connection promise
- export default mongo.connect();
导出连接承诺而不是主客户端本身将防止我们拥有冗余连接,因为我们在无服务器平台中工作。
注意我是如何使用require而不是import? 这是因为,在撰写本文时,Vercel Cloud Functions不支持 JavaScript 文件中的 ESModuleimport语句。相反,您需要使用 CommonJSrequire语句。
这里有一个问题。如果您看到package.json我们应用程序的 ,您会注意到它有一行"type": "module"。这意味着项目中的每个 JavaScript 文件都是一个 EsModule。这不是我们想要的,所以要将api目录中的所有文件都标记为 CommonJS 文件,这样我们就可以使用require语句,在其中创建api/package.json并添加这一行:
- {
- "type": "commonjs"
- }
这将允许我们在目录中使用require语句。api使用以下命令安装 MongoDB 连接驱动程序:
- # Don't forget to CD!
- cd api
- npm i mongodb # or use yarn
到目前为止,跟踪器并没有真正起作用,所以让我们解决这个问题。
对于身份验证,我们需要将用户输入的用户名存储在 MongoDB 数据库中。
创建一个文件/api/storeusername.js。这将是一个云功能,并将映射到
http://localhost:3000/api/storeusername. 将以下代码放入其中:
- const mongoPromise = require("../src/lib/mongo");
- // All cloud functions must export a function that takes a req and res object.
- // These objects are similar to their express counterparts.
- module.exports = async (req, res) => {
- // TODO
- };
接下来,像这样获取 MongoDB 客户端:
- module.exports = async (req, res) =>
- // Wait for the client to connect
- const mongo = await mongoPromise;
- }
username从请求的正文中提取:
- // ...
- const { username } = req.body;
-
- // Check if the username is valid
- if (typeof username !== "string" || !username.trim()) {
- res.status(400).json({ message: "Please send the username" });
- return;
- }
接下来,您需要将此用户名存储在数据库中:
- // Get the collection
- const usersCol = mongo.db().collection("users");
- // Check if the username already exists in the database
- if (await usersCol.findOne({ _id: username })) {
- res.status(400).json({ message: "User already exists!" });
- return;
- }
- // We want the username to be the identifier of the user
- await usersCol.insertOne({ _id: username });
-
- // Everything went well :)
- res.status(200).json({ message: "Username recorded" });
最后,这是api/storeusername.js文件的外观:
- const mongoPromise = require("./_mongo");
-
- module.exports = async (req, res)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。