在本文中,我们将逐步介绍如何使用 Cloudflare 的一些最新无服务器技术来构建一个完整的全栈应用程序 - Hono 作为 Web 框架,Workers 用于无服务器计算,R2 用于对象存储,D1 用于 SQL 数据库。这套技术栈允许你在 Cloudflare 的边缘网络上构建和部署高度可扩展的应用程序。
技术概述
以下是我们将使用的关键技术的简要介绍:
-
Hono - 一个为 Cloudflare Workers 设计的小巧、简单、快速的 Web 框架。Hono 提供了类似 Express.js 风格的中间件和路由层。
-
Cloudflare Workers - 在 Cloudflare 的边缘网络上运行的无服务器函数,使你能够在不管理基础设施的情况下构建应用程序。
-
R2 存储 - 在边缘运行的 S3 兼容对象存储,与 Workers 无缝集成。
-
D1 数据库 - 一个在 Cloudflare 的边缘与你的 Worker 一起运行的 SQL 数据库(基于 SQLite)。
通过结合这些技术,你可以构建全球分布式、快速且可自动扩展以处理任何负载的应用程序 - 所有这些都使用熟悉的范例,如 HTTP 中间件和 SQL.
设置项目
首先,确保你已经安装了最新的 Wrangler CLI 来在本地开发 Worker 项目:
npm install -g wrangler
然后用 Hono 初始化一个新的 Worker 项目:
npm init hono .
这将在当前目录中设置一个新的 Hono 项目。现在我们可以添加所需的其他依赖项:
npm install hono nanoid @cloudflare/workers-types
这将安装 Hono 框架、用于生成唯一 ID 的 nanoid,以及用于 Workers 开发的类型。
接下来,使用你的 Cloudflare 账户验证 Wrangler CLI,并在项目的 wrangler.toml
文件中配置你的账户详细信息、路由、D1 数据库绑定和 R2 存储桶绑定。
配置 Bindings
在 wrangler.toml
中定义 Bindings,告诉 Wrangler 和 Workers 运行时如何映射代码中使用的变量。对于这个示例,我们需要配置 R2 存储桶、用户名和密码:
name = "my-app" type = "javascript" account_id = "<YOUR_ACCOUNT_ID>" workers_dev = true [[r2_buckets]] binding = "MY_BUCKET" bucket_name = "<YOUR_BUCKET_NAME>" [[d1_databases]] binding = "DB" database_name = "my_db" database_id = "<YOUR_DB_ID>" [vars] USERNAME = "<YOUR_USERNAME>" PASSWORD = "<YOUR_PASSWORD>" # 其他配置...
使用适当的凭据填写这些绑定后,Wrangler 将在每次部署时设置这些环境变量,并使它们在 c.env
对象下的代码中可用。
编写服务端代码
现在让我们在 src/index.ts
中实现服务端应用程序:
import { Hono } from 'hono' import { bearerAuth } from "hono/bearer-auth"; import { logger } from 'hono/logger' import { nanoid } from "nanoid"; type Bindings = { MY_BUCKET: R2Bucket USERNAME: string PASSWORD: string } const app = new Hono<{ Bindings: Bindings }>() app.use(logger()) app.use('/api/*', bearerAuth({token: Env.TOKEN})) app.get('/', (c) => { return c.json({ ok: true }) }) app.post('/api/v1/upload', async (c) => { const key = nanoid(10) const formData = await c.req.parseBody() const file = formData['file'] if (file instanceof File) { const fileBuffer = await file.arrayBuffer() const ext = file.name.split('.').pop() const path = `images/${key}.${ext}` await c.env.MY_BUCKET.put(path, fileBuffer) return c.json({ 'image': { 'url': `${Env.HOST}${path}` }}) } else { return c.text('Invalid file', 400) } }) export default app
这里设置了几个路由:
GET /
- 健康检查端点POST /api/v1/upload
- 用于将图像上传到 R2 的身份验证端点
/upload
端点需要一个带有包含要上传图像的 file
字段的 multipart/form-data
主体。它使用 nanoid 生成一个唯一密钥,将文件上传到 R2 存储桶,并返回公共 URL。
部署到 Cloudflare
实现代码后,我们可以使用 Wrangler 在本地测试它:
wrangler dev
这将启动一个模拟 Workers 运行时的本地服务器。
准备将应用程序部署到 Cloudflare 账户时:
wrangler publish