背景
作为一名经验丰富的前端开发者,我总喜欢尝试和探索新事物。多年前,我购买了一台云服务器,并搭建了一个博客系统。回想当时的过程,我需要处理 登录
、鉴权
、数据库建表
、服务器安全
等一系列繁琐的任务,而这些并非我所擅长的领域。
不幸的是,我的系统后来遭到了黑客攻击,Mogodb 数据库中的数据被删除,黑客还留下了一段要求支付 1 个比特币
赎金的信息。这让我意识到,运维等工作确实需要专业人士来处理,而我作为业余爱好者在这方面的知识有限。因此,我一直在寻找一个免运维、安全且易于操作的平台来搭建博客。最终,我选择了腾讯云的云开发,这个平台上手简单,非常适合个人开发者使用。
本文将介绍如何利用云开发 CloudBase 部署 Nest.js 项目,并集成 Fastify。在这个过程中,我遇到了一些问题,希望本文的解决方案能为大家在类似场景下的开发提供帮助。
PS: 这些问题,即使是云开发的开发人员也未能解决。
方案
- 利用云开发的云函数部署 Node 项目,并开通外网 HTTP 访问
- 前端通过云开发的 Web SDK 发起 HTTP 请求,调用云函数的接口(这样做可以天然
免鉴权
) - 数据存储在云开发的数据库中,Node 项目中通过 云开发的 Node SDK 读写数据库
问题梳理
-
在云开发控制台无法直接部署 Nestjs 框架的云函数,需要用 CloudBase CLI 来创建
-
CloudBase CLI 最高只支持创建 Node 版本为 12.16 的云函数,但是新版的 Nestjs 的 Node 版本最低 16
-
创建好的 Nestjs 云函数是不能直接用,要进行代码改造
-
通过 @cloudbase/js-sdk 无法通过 POST 请求调用 Nestjs 框架的云函数(如果改用 request 的方式,就需要处理鉴权)
解决方案
前期准备
安装必要的依赖,这里也可以直接参考官方文档:CloudBase CLI 使用指南、 Web 端 SDK
- 前端项目中,安装 Web 端 SDK
npm install @cloudbase/js-sdk -S
- 电脑终端安装 CloudBase CLI
npm install -g @cloudbase/cli
部署 Nestjs 框架的云函数
- 首先,我们需要在腾讯云控制台手动创建一个 Node.js 16.13 的云函数。为我们部署 Nestjs 提供基础(这里记住函数名称,待会用的上)
- 使用 CloudBase CLI 创建同名云函数
直接用 CloudBase CLI 命令创建出来的 Nest.js 项目不是最新的版本,如果需要最新的 Nest.js 可以先用 Nest 官方脚手架创建项目
npm i -g @nestjs/cli
nest new project-name
现在我们开始改造项目
修改 main.ts 文件
为了让我们的 Nest.js 项目能够与云函数无缝对接,我们需要对 main.ts 文件进行一些修改。具体修改方法如下:
- 将 NestFactory.create 方法的参数从 AppModule 改为 AppModule, {adapter: new FastifyAdapter()},以使用 Fastify 作为 HTTP 服务器。
- 将 app.listen 改为 app.init,因为云函数不需要监听端口。
- 在 app.init 之前,添加 app.setGlobalPrefix('api'),以设置全局路由前缀。
import { NestFactory } from '@nestjs/core';
import {
FastifyAdapter,
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
const port = process.env.PORT || 9000;
export async function bootstrap() {
const adapter = new FastifyAdapter();
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
adapter,
);
let fastifyApp = null;
// 兼容云函数与本地开发
if (process.env.NODE_ENV === 'development') {
await app.listen(port);
} else {
fastifyApp = await app.init();
}
return fastifyApp;
}
// 开发模式下启动开发
if (process.env.NODE_ENV === 'development') {
bootstrap().then(() => {
console.log(`App listen on http://localhost:${port}`);
});
}
添加云函数所需配置
- 项目根目录下新增
app.js
文件
/* eslint-disable */
const main = require('./dist/src/main')
exports.tcbGetApp = main.bootstrap
- 项目根目录下新增
cloudbaserc.json
云函数配置文件,可以参考官方介绍
{
"version": "2.0",
"envId": "<云开发环境id>",
"$schema": "https://framework-1258016615.tcloudbaseapp.com/schema/latest.json",
"framework": {
"name": "<函数名称(`需要和之前创建的云函数名称一样`)>",
"plugins": {
"node": {
"use": "@cloudbase/framework-plugin-node",
"inputs": {
"name": "<函数名称>",
"path": "<自定义访问路径>",
"entry": "app.js",
"buildCommand": "npm install --prefer-offline --no-audit --progress=false && npm run build",
"functionOptions": {
"timeout": 5,
"envVariables": {
"NODE_ENV": "production"
},
"memorySize": "256"
}
}
}
}
},
"functionRoot": "./functions",
"functions": [],
"region": "<函数所在地域>"
}
- 修改打包配置 package.json
记得要安装 @cloudbase/cli,不然会找不到 tcb 命令
// 新增一条部署命令
"scripts" {
// ...
"deploy": "tcb framework deploy"
}
接下来,我们需要运行npm run deploy
命令部署同名云函数
设置 @cloudbase/js-sdk 的请求头
前端在使用 @cloudbase/js-sdk 请求部署 Nest.js 的云函数时,我们需要设置请求头,以解决无法调用 POST 请求的问题。具体设置方法如下:
import cloudbase from '@cloudbase/js-sdk';
// 封装 tcb 云函数请求
export const tcbRequest = async ({ path = '', data = {} }) => {
// 参数拼接
const queryString = Object.entries(data)
.map(([key, value]) => `${key}=${value}`)
.join('&');
const app = cloudbase.init({
env: 'xxx', // 您的环境id
})
const { result } = await app.callFunction({
name: 'scf-name',
data: {
path,
httpMethod: 'POST',
isBase64Encoded: false,
body: queryString,
headers: {
'content-type': 'application/x-www-form-urlencoded',
},
},
});
// 返回结果解析
const { body } = result || {};
const response = JSON.parse(body || '{}');
if (response.status === 0) {
return response.data;
}
console.error(JSON.stringify(response.message));
return null;
};
验证
可以看到我调用的登录,Web SDK 自动处理 token
和 refresh_token
相关的逻辑。调用业务接口,云函数也能正常返回数据,不过数据是序列化之后的,前端只需要反序列化就可以了。是不是很方便?
结束
通过以上几个步骤,我们成功地将 Nest.js 项目部署到了腾讯云云开发,并集成了 Fastify。同时,我们也解决了 Node 版本和云函数调用的问题。希望本文对大家在类似场景下的开发有所帮助。
欢迎大家 点赞 + 评论 + 收藏