怎么构建有推送通知的 GitHub 跟踪器,你知道吗

在本文中,您将学习如何构建一个 GitHub 跟踪器,当跟踪的存储库中有新的问题/PR 时,它会通过发送推送通知来通知用户。

如果您选择加入,GitHub 已经通过电子邮件发送通知,但许多研究表明,推送通知比电子邮件更能吸引用户。按照本教程构建 GitHub 跟踪器后,您将学会如何:

  • 添加服务工作者并将跟踪器转换为PWA
  • 订阅推送通知
  • 使用GitHub API
  • 通过Vercel云函数发送推送事件
  • 使用EasyCron定期获取新问题

先决条件

阅读本文需要一些技能和服务:

  • 安装了Node.js和 npm
  • 先前的Svelte知识
  • 一个免费的GitHub帐户,因为我们使用的是GitHub API
  • 一个免费的MongoDB Atlas帐户,用于在云中使用 MongoDB
  • 用于部署应用程序和云功能的免费Vercel帐户

什么是推送通知?

让我们来看看这些所谓的“推送通知”是什么。

您必须熟悉定期通知。这些是出现在屏幕上的小气泡文本,用于通知您某些事情。推送通知类似,只是它们不是按需生成的,而是在接收推送事件时生成的。推送通知在应用程序关闭时起作用,而常规通知要求您打开应用程序。

现代 Web 浏览器(如 Chrome)通过使用称为服务工作者的东西支持推送通知。Service Worker 是独立于浏览器主线程运行的一小段 JavaScript,因此,如果您的应用程序安装为 PWA(渐进式 Web 应用程序),则可以离线运行。

推送通知用于聊天应用程序中以在用户有未读消息时通知用户,在游戏中,通知用户游戏事件,在新闻站点中,通知用户突发文章,以及用于许多其他目的。

在您的应用程序中显示推送通知有四个步骤:

  1. 请求许可window.Notification.requestPermission()
  2. 将您的应用程序转换为游戏 PWA 并安装它
  3. 订阅推送事件
  4. 收到推送事件后,发送通知

第 1 步:创建跟踪器

让我们在本文中使用 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到之前的代码!

第 2 步:设置云功能

我们需要有一个后端服务器来向我们的应用程序发送推送事件。这意味着您需要创建一个新的(可能)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();

导出连接承诺而不是主客户端本身将防止我们拥有冗余连接,因为我们在无服务器平台中工作。

使用 CommonJS 而不是 ESModules

注意我是如何使用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

第 3 步:添加功能

到目前为止,跟踪器并没有真正起作用,所以让我们解决这个问题。

验证

对于身份验证,我们需要将用户输入的用户名存储在 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) => {
  cons
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值