Cloudflare Workers 上手：从零到部署一个短链接服务

Cloudflare Workers 是一个无服务器（Serverless）平台。用它构建的应用可以享受 Cloudflare 遍布全球的边缘网络——你的代码会在离用户最近的节点运行。它支持 TypeScript、JavaScript、Python、Rust 等语言（当然，大部分人都用 TS/JS）。无服务器意味着什么？无服务器 = 无状态（Stateless）。好处是可扩展性极强：请求来了，Cloudflare 会在全球各个节点瞬间启动实例来处理。底层用的是 V8 引擎，冷启动飞快。请求处理完，实例就休眠了。限制是数据无法持久化——但这不是问题，Cloudflare 提供了一整套配套服务：服务用途 KV 键值对存储（本文会用到） D1 SQLite 数据库 R2 对象存储（S3 兼容） Queues 异步任务队列 Workflows 持久化工作流 Workers AI AI 推理再加上开箱即用的日志和可观测性，基本上什么类型的应用都能构建了。今天我们就来上手一下：写一个简单的 React 应用，再加一个短链接生成功能，最后部署上去。前提：一个 Cloudflare 账号 + Node 环境。创建项目 pnpm create cloudflare@latest my-react-app --framework=react 一路回车即可。项目结构概览 my-react-app/ ├── src/ # React 前端源代码 │ ├── App.tsx │ ├── main.tsx │ └── ... ├── worker/ # Cloudflare Workers 后端代码 │ └── index.ts # Worker 入口 ├── wrangler.jsonc # 核心配置文件（部署、资源绑定） ├── worker-configuration.d.ts # 自动生成的类型定义 ├── vite.config.ts ├── package.json └── tsconfig.*.json 重点关注两个地方： worker/ 目录：后端逻辑 wrangler.jsonc：基础设施即代码（Infrastructure as Code）核心配置：wrangler.jsonc 这个文件定义了你的 Worker 需要什么资源。部署时 Cloudflare 会根据它来分配资源。 { "$schema": "node_modules/wrangler/config-schema.json", "name": "my-react-app", "main": "worker/index.ts", "compatibility_date": "2025-09-27", "assets": { "not_found_handling": "single-page-application" }, "observability": { "enabled": true } } Worker 入口 // worker/index.ts export default { fetch(request) { const url = new URL(request.url); if (url.pathname.startsWith("/api/")) { return Response.json({ name: "Cloudflare" }); } return new Response(null, { status: 404 }); }, } satisfies ExportedHandler; 就是一个 fetch handler，你来决定怎么处理请求。模板代码处理了 /api/ 路径，返回一段 JSON，其余返回 404。类型生成 worker-configuration.d.ts 是根据 wrangler.jsonc 自动生成的类型文件，让 TypeScript 能识别你绑定的资源（KV、D1、环境变量等）。每次改完配置文件，运行一下： pnpm cf-typegen 跑起来 pnpm dev 打开页面，点击按钮，就能看到从后端接口返回的 "Cloudflare"。实战：短链接生成器接下来整点实际的——用 KV 存储做一个短链接服务。绑定 KV 资源修改 wrangler.jsonc： { "$schema": "node_modules/wrangler/config-schema.json", "name": "my-react-app", "main": "worker/index.ts", "compatibility_date": "2025-09-27", "assets": { "not_found_handling": "single-page-application", "run_worker_first": ["/s/*", "/api/*"] }, "observability": { "enabled": true }, "kv_namespaces": [ { "binding": "KV" } ] } 两个关键改动： run_worker_first：指定哪些路径由 Worker 处理，否则会被前端 SPA 接管 kv_namespaces：绑定一个 KV 命名空间，变量名叫 KV 然后重新生成类型： pnpm cf-typegen 安装 Hono 手写 if/else 路由太累了，装个轻量级框架： pnpm add hono 编写后端逻辑 // worker/hono.ts import { Hono } from "hono"; export const app = new Hono<{ Bindings: Env }>(); // 生成短链接 app.post("/api/set-link", async (c) => { const body = await c.req.json<{ link: string }>(); let link = body.link; // 确保链接以 http(s) 开头 if (!/^https?:\/\//i.test(link)) { link = "https://" + link; } // 生成 6 位随机 ID const id = Math.random().toString(36).substring(2, 8); // 写入 KV await c.env.KV.put(id, link); return c.json({ id }); }); // 短链接跳转 app.get("/s/:id", async (c) => { const id = c.req.param("id"); const link = await c.env.KV.get(id); if (!link) { return c.json({ error: "Link not found" }, 404); } return c.redirect(link); }); 通过 c.env.KV 就能访问绑定的 KV 资源，类型提示完美。修改入口文件 // worker/index.ts import { app } from "./hono"; export default { fetch(request, env, ctx) { return app.fetch(request, env, ctx); }, } satisfies ExportedHandler; 前端页面 😋让AI简单写个输入框和按钮及样式： /* App.css */ #root { max-width: 1280px; margin: 0 auto; padding: 2rem; text-align: center; font-family: system-ui, -apple-system, sans-serif; } .container { display: flex; flex-direction: column; align-items: center; gap: 2rem; margin-top: 10vh; } h1 { font-size: 2.5rem; margin-bottom: 1rem; } .input-group { display: flex; gap: 10px; width: 100%; max-width: 600px; } input { flex: 1; padding: 12px; border-radius: 8px; border: 1px solid #444; background: #2a2a2a; color: white; font-size: 1rem; } button { padding: 12px 24px; border-radius: 8px; border: 1px solid transparent; background-color: #646cff; color: white; cursor: pointer; font-weight: bold; font-size: 1rem; transition: background-color 0.25s; } button:hover { background-color: #535bf2; } .result { margin-top: 2rem; padding: 2rem; background: #1a1a1a; border-radius: 12px; width: 100%; max-width: 500px; } .link-box { display: flex; align-items: center; justify-content: center; gap: 1rem; margin-top: 1rem; padding: 1rem; background: #000; border-radius: 8px; } a { color: #646cff; text-decoration: none; word-break: break-all; } a:hover { text-decoration: underline; } // src/App.tsx import { useState } from 'react' import './App.css' function App() { const [inputUrl, setInputUrl] = useState('') const [shortLink, setShortLink] = useState('') const [loading, setLoading] = useState(false) const handleShorten = async () => { if (!inputUrl) return; setLoading(true); try { const res = await fetch('/api/set-link', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ link: inputUrl }) }); const data = await res.json() as { id: string }; const protocol = window.location.protocol; const host = window.location.host; setShortLink(`${protocol}//${host}/s/${data.id}`); } catch (e) { console.error(e); alert('Failed to shorten link'); } finally { setLoading(false); } }; return (

短链接生成器

setInputUrl(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleShorten()} /> {loading ? '...' : '生成短链接'}
{shortLink && (

短链接:

{shortLink} navigator.clipboard.writeText(shortLink)}> 复制

)}
) } export default App 本地 pnpm dev 测试一下，功能正常就可以部署了。部署一条命令： pnpm run deploy 第一次会让你登录授权。然后你会看到类似这样的输出： ✨ Read 5 files from the assets directory ✨ Success! Uploaded 4 files (1.22 sec) Provisioning KV (KV Namespace)... 🌀 Creating new KV Namespace "my-react-app-kv"... ✨ KV provisioned 🎉 Deployed my-react-app triggers (1.26 sec) https://my-react-app.xxxxx.workers.dev Cloudflare 会自动帮你创建 KV 资源，并把生成的 ID 写回 wrangler.jsonc： "kv_namespaces": [ { "binding": "KV", "id": "62ff346972fe40d3b23cebb679ea4d68" } ] 在 wrangler 4.45.0 之前，你得先手动创建 KV、拿到 ID、填进配置文件。现在不用了，部署时自动搞定。打开分配的 *.workers.dev 域名，你的短链接服务就上线了。小结 Cloudflare Workers 的开发体验相当丝滑：本地开发：pnpm dev，热更新，KV 也能本地模拟类型安全：wrangler types 自动生成绑定类型一键部署：pnpm deploy，资源自动创建如果你想快速搭建一个全球可用的小应用，Workers 是个很好的选择。