前端5分钟技术转全栈!orpc + cloudflare 项目实践
前言
标题党了一下哈哈,全栈还是有很多知识要学习的,这里只是简单介绍一套我觉得还不错的技术栈,希望对大家有帮助。
大前提: 请先注册一个 cloudflare 账户。5块钱买个域名绑定到 cloudflare 上,可以参考我之前的文章。
快速创建项目
我在 GitHub 上偶然发现了一个很有意思的项目,想推荐给大家: www.better-t-stack.dev/new
它提供了一个可视化页面,可以自由选择自己需要的技术栈,并自动生成初始化命令,一行命令就能创建完整项目。即使对技术栈不太熟悉,也可以直接使用社区中使用人数较多的预设配置,例如左下角提供的 T3 Stack、PERN Stack 等方案。同时还支持在线预览项目的文件结构,整体体验做得相当成熟。
这次我选择的是前后端统一部署到 Cloudflare,运行时使用 Cloudflare Workers,前后端之间通过 oRPC 通信。对于技术栈中一些不太熟悉的部分,我会在后文单独说明。通过复制生成的命令行即可完成项目初始化,最终得到的是一个前后端共存的 monorepo 项目结构,使用 Turbo 统一管理前后端的运行、调试和构建流程。
前后端代码全部采用 TypeScript 编写,对前端同学非常友好,上手成本也很低。(题外话: 我觉得写 JS / TS真幸福,应了那句话: 能用 JS 写的最后都用 JS 写😂)
pnpm create better-t-stack@latest cf-todo --frontend tanstack-router --backend hono --runtime workers --api orpc --auth none --payments none --database sqlite --orm drizzle --db-setup d1 --package-manager pnpm --git --web-deploy cloudflare --server-deploy cloudflare --install --addons biome turborepo --examples todo
运行项目
我们先把项目运行起来再看看代码。根据提示先运行一些Database的命令。pnpm run db:generate
然后启动本地看看效果 pnpm run dev (注: 如果项目运行不起来,尝试升级一下pnpm版本,这个monorepo借助了pnpm-workspace的特性,一些 catalog 可能需要 pnpm 高版本才支持。)
可以看到项目运行成功分别在本地 3001、3002端口,作者贴心的展示了一个TODO list示例。
了解代码
文件结构
很清爽的文件结构,apps下有前后端,然后packages下是一些共用的内容,根目录是格式化的biome与pnpm与turbo的配置。
Pnpm-workspace
www.pnpm.cn/catalogs 使用了catalogs 方便在各个子包中共享同一个npm包避免重复安装。
然后在 /apps/web/package.json 与 /apps/server/package.json 我们就可以看到使用根目录的catalogs了。
www.pnpm.cn/workspaces workspaces 方便引用同一工作区的其他子模块的文件。
Hono
Hono 是一个轻量级的 Web 框架,主要面向 JavaScript 和 TypeScript 生态。它的设计目标是高性能、低开销,以及在不同运行时环境中的一致体验
官网: hono.dev/ ,常用与于 cloudflare 想结合出现。nodejs backend 框架也是多种多样的,选择自己喜欢的即可。
ORPC
orpc 简单讲就是 trpc 的进化版。
trpc可能有的同学也不是很了解,引用自官网的介绍 快速迭代,无忧无虑。轻松构建端到端类型安全的 API 。
说人话就是前后端共用一套TS,然后前端调用接口就可以直接以函数调用的方式访问后端接口,前端可以直接获得后端暴露的 API 类型定义。不用传统的前后端联调,后端给openapi文档,前端生成对应的TS接口响应入参与出参了,直接一套前端要调用接口直接点出来。
orpc 就是在 trpc 的基础上进行改造,官网: orpc.dev/docs/gettin… oRPC(开放 API 远程过程调用)结合了 RPC(远程过程调用)与 OpenAPI,允许您通过类型安全的 API 定义和调用远程(或本地)过程,同时遵循 OpenAPI 规范。 可以在享受trpc的同时生成openapi规范的文档。
访问我们这个示例项目的 http://localhost:3000/api-reference 就可以看到一个美观的openapi规范的在线接口示例
我们来看orpc有多方便。
packages\api\src\routers\todo.ts 接口的定义
apps\web\src\routes\todos.tsx 前端界面直接调用点出来要使用的函数。然后用 @tanstack/react-query 相关的hook进行处理,
orpc也可以很好的与tanstack-query相结合。这样子直接开发个人项目的时候就免去了接口联调的麻烦,写完后端前端直接调用。
drizzle
drizzle orm 就是方便你来增删改查数据的,在没有这些ORM的时候需要直接写SQL语句执行,有了这些ORM他们封装了一些方法让你更轻松的掌控数据。然后实在复杂的SQL也可以自定义。
node的ORM选择有蛮多的 选自己喜欢的或者大家推荐比较多的即可。
Alchemy
这个东西我也是第一次见到,我直接在bing搜还搜不到 需要加一些关键词,但感觉做的还不错,这里是官网: alchemy.run/what-is-alc… 简单讲就是帮你管理一些部署用的基础设施信息,我这里是部署到 cloudflare,然后有一个 alchemy.run.ts 文件就是管理全部部署到 cloudflare相关的事情。
如果你尝试 pnpm run deploy 部署这个项目的时候会发现运行不成功,因为你还没有给本地的 alchemy 授权你的 cloudflare 账户。
npm i -g alchemy安装完成后 alchemy configure 会打开一个授权页授权到本地即可。如果打不开或授权失败,请尝试打开vpn的 TUN 模式试下。
Turborepo
Turborepo 是一个用于 JavaScript 和 TypeScript 代码库的高性能构建系统。它专为扩展单体仓库而设计,也能加速单包工作区中的工作流。
vercel开源的一个项目,常用于处理 monorepo 类型仓库的构建。
Cloudflare
我们这个项目前后端都部署到 cf 的 woker上,有很多的免费额度,cf真是大善人。然后数据存储的数据库使用的也是 cf 的D1数据库,个人MVP的项目初期应该够用了,升级了也不贵,不愧是赛博佛祖。
项目部署
授权完成后,我们运行 pnpm run deploy 试一下。可以看到给出了前后端两个地址。
访问前端后发现,我靠这么请求的是localhost:3000, 原来我们前后端的 .env 文件都没进行修改。
在后端的根目录创建一个.env.dev文件,CORS_ORIGIN 填写前端访问的地址。
CORS_ORIGIN=[填写前端地址]
前端创建一个 .env.dev文件
VITE_SERVER_URL=[填写后端地址]
然后添加一个 pnpm run deploy:dev 命令在根目录的 package.json 文件,表示我们要对 env.dev 环境变量的内容进行打包构建。复制上一行的 deploy 命令基础上再添加了一个 ALCHEMY_ENV=dev 的标识。
"deploy:dev": "cross-env ALCHEMY_ENV=dev turbo -F @cf-todo/infra deploy",
再修改 alchemy.run.ts 文件,根据环境变量读取对应的env文件
import alchemy from "alchemy";
import { D1Database, Vite, Worker } from "alchemy/cloudflare";
import { config } from "dotenv";
const mode = process.env.ALCHEMY_ENV ?? process.env.NODE_ENV ?? "development";
const loadEnv = (path: string, override = false) => {
config({ path, override });
};
loadEnv("./.env");
loadEnv(`./.env.${mode}`, true);
loadEnv("../../apps/web/.env");
loadEnv(`../../apps/web/.env.${mode}`, true);
loadEnv("../../apps/server/.env");
loadEnv(`../../apps/server/.env.${mode}`, true);
const app = await alchemy("cf-todo");
const db = await D1Database("database", {
migrationsDir: "../../packages/db/src/migrations",
});
export const web = await Vite("web", {
cwd: "../../apps/web",
assets: "dist",
bindings: {
VITE_SERVER_URL: alchemy.env.VITE_SERVER_URL!,
},
});
export const server = await Worker("server", {
cwd: "../../apps/server",
entrypoint: "src/index.ts",
compatibility: "node",
bindings: {
DB: db,
CORS_ORIGIN: alchemy.env.CORS_ORIGIN!,
},
dev: {
port: 3000,
},
});
console.log(`Web -> ${web.url}`);
console.log(`Server -> ${server.url}`);
await app.finalize();
最后还需要在turbo.json 文件添加下构建传递的这个标识变量。
"deploy": {
"cache": false,
"env": ["ALCHEMY_ENV"]
},
重新部署
先运行 pnpm run destory 销毁之前的资源。再执行 pnpm run deploy:dev。nice 可以使用了,美滋滋~
结语
现在,一个简单完整的前后端项目已经准备好,并且可以零成本完成部署,已经交到你手里了。接下来就可以充分发挥想象力和创造力,去打磨一个让人眼前一亮的产品。你也可以选择继续深入研究这个项目,从中学习和理解当前主流的工程化实践与技术选型思路。希望对大家有帮助!
改造部署文件参考: github.com/LLmoskk/orp…
最后,感恩Cloudflare!感恩 better-t-stack.dev/new 项目!