xiaofuyesnew

V1

2023/02/14阅读:46主题:默认主题

从 Vercel 到 PlanetScale

本文详细介绍如何使用 Vercel 的 Serverless 功能为项目添加 API ,并使用 Prisma 连接 PlanetScale 数据库。

本文将不会涉及且基于读者已熟知并建立以下环境:

  • 开发环境(Node.js/Git/VSCode...)
  • Github 账号
  • 科学上网

配置开发分支

承接上文,当我们向 Github 远程仓库推送代码后,Github Actions 和 Vercel 就会分别对代码进行构建和部署。

频繁的 commit 操作显然会消耗过多的构建和部署时长。对于 Github 来说,免费用户的构建时长是每月 2000 分钟;而对于 Vercel 来说,免费用户的构建时长是每月 6000 分钟。虽然免费额度不太可能用完,但频繁的构建确实显得浪费且没有必要。

因此,我们可以从本地项目代码中迁出一个 dev 分支,用于日常的开发:

$ git checkout -b dev
# 与远程仓库同步
$ git push -u origin dev

此时,对于触发构建的条件,我们有两种选择:其一,在 dev 分支开发完成后,将代码合并到 main 分支,再由 main 分支进行 push 操作触发构建,此种情况不用更改 workflow 脚本;其二,在 dev 分支开发完成后,push 到远程仓库,由远程仓库的 dev 分支向 main 分支提交 pull request 再触发构建,此种情况则需要对 .github/workflows/pages.yml 文件做如下修改:

...
on:
  # push:
  pull_request:
    branches: [main]
...

当然,也可以保留两者,适用于任何代码合并的场景。

使用 Vercel 的 Serverless

Serverless 初体验

Vercel 本身是具备 Serverless 功能的,可以单独新建项目开发纯粹的 API 服务;而对于具有前端部分的项目,需要在项目根目录下创建 api 目录(只能命名为 api )来当做 Serverless 的根目录。

进入 api 目录,并将其初始化:

$ cd api
$ pnpm init

如果你喜欢 ES module 方式导入模块,可以在生成的 package.json 中加入字段:

{
  ...
  "type""module"
  ...
}

也可以不加,就会自然保持 commonjs 的导入方式。下文中的代码示例,都是以 ES module 为例。

api 目录下新建 index.js 文件,然后简单写一个 Serverless :

export default async (req, res) => {
  const data = {
    msg'Hello world!'
  }
  
  res.status(200).json(data)
}

提交 commit 构建部署后,在浏览器中直接打开 <project url>/api ,如果看到以下内容,则说明 API 部署成功:

{
  msg: "Hello world!"
}

设置 Serverless 的开发模式

Vercel 提供了开发模式,便于在本地进行开发,而不用频繁部署到生产环境中,开启 Serverless 的开发模式,只需要在本地项目目录下执行如下命令:

# Vercel 命令行登录授权
$ npx vercel auth login
# 开启 Serverless 本地开发模式
$ npx vercel dev

命令会简单询问你几个问题,依次绑定好对应的权限和项目即可:

此时,在浏览器中访问 localhost:3000/api 即可看到在本地运行 Serverless 的返回结果。

如果同时要兼顾页面和接口的开发,有两种命令行方案:

  1. 打开两个终端窗口,分别执行 npx vercel devvite :

优点是各自的终端信息比较全面不会互相干扰;

缺点是需要打开两个窗口和执行两次命令。

  1. package.json 中注册一个 script:
{
  ...,
  "scripts": {
    ...,
    "vercel:dev""npx vercel dev | vite"
  }
}

然后执行 pnpm vercel:dev 即可同时启动开发环境下的页面和接口服务。

优点是只需要开启一个终端界面,并执行一个指令就可以开启所有服务;

缺点是所有信息混在在一起,对各个开发部分会有一定干扰。

由于在开发环境中,页面和接口的服务在不同的端口提供,在页面开发中直接请求接口会有跨域限制,我们需要在 vite.config.js 中配置代理:

import { defineConfig } from 'vite'

export default defineConfig({
  ...,
  server: {
    proxy: {
      '/api': {
        target'http://localhost:3000/api',
        changeOrigintrue,
        rewrite(path) => path.replace(/^\/api/''),
      }
    }
  }
})

这样在请求时,只需要请求 /api 则会代理到本地的接口服务。同时,由于在 Vercel 生产环境页面和接口服务是同域名,则不存在跨域的情况,因此在生产环境可以不用做更多的处理。

PlanetScale 和 Prisma

PlanetScale 数据库的创建和配置

打开 planetscale.com ,同样可以使用 Github 账号进行授权登录。

PlanetScale 为免费用户提供了一个免费的数据库,这个数据库可以包含两个分支,同时,有一定的使用限制,如下图所示:

但对于一个个人博客项目来说,这个额度是足够的。

登录后,我们可以创建一个数据库:

通过 Region 来选择数据库实例所在的节点,建议根据地理位置选择离自己更近的节点。

创建好数据库后,可以点击 New Branch 创建一个开发分支,如下图:

创建好分支后,在任一分支的 Overview 界面下,点击 Promote a branch to production 按钮,来指定一个生产环境分支:

一般地,我们将 main 分支作为生产环境分支,而 dev 作为开发环境分支。

在两个分支的 Overview 界面中点击 Connect 按钮,PlanetScale 会生成对应数据库的连接凭证:

可以更改 Connect with 选项,查看不同连接方式的凭证使用介绍,此处我们选择 Prisma :

将获取到的 DATABASE_URL 参数填写到 Vercel 项目配置的 Environment Variables 中配置环境变量:

这里,需要配置两个 DATABASE_URL 分别在开发环境和生产环境,对应 PlanetScale 数据库的开发分支和生产分支的访问凭证。

访问凭证配置在此处的目的是为了使敏感信息更安全,而不会随项目代码暴露出去。

使用 Prisma 连接数据库

让我们暂时回到本地项目目录,来到 api 目录,添加依赖,并初始化 Prisma :

$ pnpm add @prisma/client
$ pnpm add prisma -D
$ npx prisma init

初始化过程会在目录下生成 prisma/schema.prisma.env

prisma/schema.prisma 中写入如下内容:

// 生成客户端
generator client {
  provider = "prisma-client-js"
}

// 数据源连接凭证
datasource db {
  provider     = "mysql"
  url          = env("DATABASE_URL")
  relationMode = "prisma"
}

// User 数据表描述
model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
}

.env 中写入如下内容:

DATABASE_URL='mysql://root@127.0.0.1:3309/<database name>'

其中,<database name> 为 PlanetScale 上创建的数据库名称。

安装 PlanetScale CLI :

https://github.com/planetscale/cli/releases

从以上地址可以获取 PlanetScale CLI 的各平台最新版本,下载后解压后放置在任意路径,并将该路径注册进系统的环境变量中

在终端中使用 pscale version 来检测安装是否成功。

在终端中输入命令:

# 弹出页面验证授权
$ pscale auth login

#
 连接数据库,并代理到本地 3309 端口
$ pscale connect <database name> <branch name> --port 3309

其中,<database name> 为数据库名称, <branch name> 为分支名称,此处可以为我们设置的开发分支 dev

本地代理端口可以更改,但需与 .envDATABASE_URL 描述的端口保持一致。

然后再打开一个终端,输入命令:

$ npx prisma db push

执行完毕后,我们可以去查看 PlanetScale 的控制台的 Schema 界面,里面有相应的 User 表,则证明我们的数据结构操作已经成功:

此时,就可以在数据表中添加一些数据,此处笔者直接使用 Prisma studio 进行操作:

$ npx prisma studio

在弹出的页面中操作添加一条记录:

接下来,我们处理一下 Serverless 的代码。

首先,我们在 api 目录下创建 lib/prisma.js ,其内容如下:

import { PrismaClient } from '@prisma/client'

const prisma = global.prisma || new PrismaClient()

if (process.env.NODE_ENV === 'development') global.prisma = prisma

export default prisma

其目的在于在开发环境下创建 PrismaClient 的单例。

然后,我们修改一下 index.js 的内容:

import prisma from './lib/prisma.js'

export default async (req, res) => {

  const users = await prisma.user.findMany()

  const data = {
    msg'Hello world!',
    data: users
  }

  res.status(200).json(data)
}

开启本地开发服务,访问 localhost:3000/api 就会得到如下结果:

{
  msg: "Hello world!",
  data: [
    {
      id: 1,
      email: "test_user@test.com",
      name: "user_development"
    }
  ]
}

说明在开发环境中,完整打通了从 Serverless 到数据库的开发链路,可以进一步编写接口的业务逻辑。

数据库部署

当我们开发好相关的 Serverless 功能,数据库结构也相应固定下来时,就可以进行部署操作了。

前文已经介绍了 Serverless 的部署,此处不再赘述,但需要补充的是,因为 Vercel Serverless 的构建不会进行 Prisma Client 的生成,因此需要在提交代码部署之前于 api 目录下的 package.json 中添加一条 script 钩子

{
  ...,
  "scripts": {
    ...,
    "postinstall""prisma generate"
  }
}

下面我们着重介绍数据库的部署:

首先,我们需要将数据库的 dev 分支通过 deploy request 合并到 main 分支上:

当确认 deploy request 之后,两表的结构就合并了。

然后,在终端窗口建立数据库生产分支的代理:

$ pscale connect tutorial main --port 3309

打开一个新的终端,使用 Prisma studio 连接数据库:

$ npx prisma studio

创建一条记录:

然后,确保 Serverless 部署和数据库都准备妥当后,访问 <project url>/api ,如果出现以下内容:

{
  msg: "Hello world!",
  data: [
    {
      id: 1,
      email: "test_user@test.com",
      name: "test_production"
    }
  ]
}

则说明部署生产环境已经成功。

总结

在本文中,我们首先区分了项目的开发环境和生产环境,并从 Vercel 的 Serverless 功能出发,通过 Prisma 在 Serverless 中添加访问 PlanetScale 数据库的能力。

至此,一套完整的、围绕 Github, Vercel, PlanetScale, Prisma 功能的个人博客系统开发工作流已经完全打通,后续的关注点就将逐步转移到具体业务功能的实现上。


前文拾遗

在上文中,我们创建了 gh-pages 分支用于承载构建后的文件,用于部署至 Github Pages 。但在触发 Vercel 构建后,Vercel 会进行 Preview Deployment ,而它的默认拉取分支就是 gh-pages 。这会造成 Vercel 的构建错误,如下图:

解决方法就是,在项目的 Settings > Git > Ignored Build Step 中配置:

# Command
[ "$VERCEL_ENV" != production ]

这可以阻止触发 非production 的构建。

同时,因为构建会触发 Github 通知,会默认发送通知和邮件,如果觉得没有必要或觉得受到打扰,可以在项目中添加 vercel.json 配置文件,然后增加如下部分:

{
  ...,
  "github": {
    "silent"true
  }
}

如对该文章涉及到的话题感兴趣,可关注

【开源说】微信公众号

回复【关注】或【作者】

长按二维码加好友,备注【开源说】

分类:

前端

标签:

工具介绍

作者介绍

xiaofuyesnew
V1

武汉般若互动-前端TL