使用 Vercel Edge 上的 PlanetScale 和 Prisma 向我的 Astro 博客添加评论

本文介绍了作者如何在其Astro博客平台上添加评论功能,选择了PlanetScale作为无服务器MySQL数据库,并使用Prisma作为ORM。由于在Vercel Edge部署,需要特殊处理数据库连接。作者详细阐述了设置Prisma、PlanetScale的过程,以及如何在前端(React)和API路由中创建和列出评论。最后,讨论了在Vercel Edge上部署Astro的配置细节。
摘要由CSDN通过智能技术生成

在我使用 Astro 创建我的博客平台后,我列表中的下一件事是让人们可以(匿名)在博客文章上发表评论。
为此,我需要在我的架构中添加一个数据库。

技术选择

我选择PlanetScale 是因为它是无服务器和 MySQL,这是我的两个标准。
为了与我的 PlanetScale 数据库通信,我选择使用Prisma,一个 Node.js 和 TypeScript ORM。

设置棱镜

我首先添加 Prisma 客户端:npm install prisma @prisma/client.
安装后,我将 Prisma 模式添加到我的代码库中:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>// schema.prisma

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["referentialIntegrity"]
}

datasource db {
  provider     = "mysql"
  url          = env("DATABASE_URL")
  relationMode = "prisma"
}

model Post {
  id         Int       @id @default(autoincrement())
  createdAt  DateTime  @default(now())
  url        String
  like_count Int @default(0)
  Comment    Comment[]
}

model Comment {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  text      String
  author    String
  postId    Int
  post      Post     @relation(fields: [postId], references: [id], onDelete: Cascade)
}
</code></span></span>

然后它变得有点棘手。
因为我是在Vercel的Edge网络上部署我的博客平台,平台到数据库的连接不能有持久连接
经过一些研究,我发现 Prisma 提供了一个名为Prisma Data Platform.
一旦我在数据平台上创建了一个帐户,我就能够创建一个Data Proxy,它为我提供了一个连接字符串以在我的应用程序中使用。
这个连接字符串是我需要放入DATABASE_URL环境变量中的(在 中使用prisma.schema)。

为了根据我的 Prisma 架构生成 TypeScript 类型,我刚刚运行了,默认情况下,这将在本地项目的文件夹npx prisma generate中生成类型。node_modules

设置 PlanetScale

将模式从 Prisma 同步到 PlanetScale 就像npx prisma db push在终端中运行一样简单。

创建评论

为了从我的前端与我的 API 路由进行通信,我选择使用TanStack Query,这是我最喜欢的工具,用于在 React 中处理客户端 API 调用。
为博客文章添加和列出评论的前端代码如下所示(这部分我用 React 编写):

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">Comment</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">@prisma/client</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">useQuery</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">@tanstack/react-query</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">useRef</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">Fragment</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">react</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">CommentsUpvotes</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">({</span>
  <span style="color:var(--syntax-name-color)">initialComments</span><span style="color:var(--syntax-text-color)">,</span>
  <span style="color:var(--syntax-name-color)">blogUrl</span><span style="color:var(--syntax-text-color)">,</span>
<span style="color:var(--syntax-text-color)">}:</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-text-color)">initialComments</span><span style="color:var(--syntax-text-color)">?:</span> <span style="color:var(--syntax-name-color)">Comment</span><span style="color:var(--syntax-text-color)">[];</span>
  <span style="color:var(--syntax-text-color)">blogUrl</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">})</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">formRef</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useRef</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">HTMLFormElement</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">null</span><span style="color:var(--syntax-text-color)">);</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">formState</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setFormState</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">idle</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-error-color)">|</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">loading</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">idle</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">);</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">upToDateCommentsQuery</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useQuery</span><span style="color:var(--syntax-text-color)">({</span>
    <span style="color:var(--syntax-name-color)">queryKey</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-string-color)">`comments-</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">blogUrl</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">],</span>
    <span style="color:var(--syntax-name-color)">queryFn</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">async</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">allCommentsInDb</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span>
        <span style="color:var(--syntax-string-color)">`/api/comments/list?blogUrl=</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">blogUrl</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span>
      <span style="color:var(--syntax-text-color)">);</span>
      <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">allCommentsInDbJson</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">allCommentsInDb</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">json</span><span style="color:var(--syntax-text-color)">();</span>
      <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">allCommentsInDbJson</span> <span style="color:var(--syntax-declaration-color)">as</span> <span style="color:var(--syntax-name-color)">Comment</span><span style="color:var(--syntax-text-color)">[];</span>
    <span style="color:var(--syntax-text-color)">},</span>
    <span style="color:var(--syntax-name-color)">initialData</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">initialComments</span><span style="color:var(--syntax-text-color)">,</span>
  <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">onSubmit</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">async</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">e&
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值