Cloudflare Workers 部署实战:从零到生产
作者:君知博客团队
52 分钟阅读
#Cloudflare#Workers#边缘计算#部署#性能优化
Cloudflare Workers 部署实战:从零到生产
Cloudflare Workers 是一个强大的边缘计算平台,可以让你的应用在全球 200+ 个数据中心运行。本文将详细介绍如何部署和优化你的应用。
什么是 Cloudflare Workers?
Cloudflare Workers 是基于 V8 引擎的无服务器平台,运行在 Cloudflare 的边缘网络上。
主要优势
- 全球分布:在 200+ 个城市运行,用户访问最近的节点
- 极速响应:平均响应时间 < 50ms
- 无冷启动:不像传统 Serverless,Workers 没有冷启动问题
- 免费额度:每天 100,000 次请求免费
- 简单定价:超出免费额度后,$5/月 1000 万次请求
环境准备
1. 安装 Wrangler CLI
# 使用 npm 安装
npm install -g wrangler
# 或使用 pnpm
pnpm add -g wrangler
# 验证安装
wrangler --version
2. 登录 Cloudflare
# 登录你的 Cloudflare 账号
wrangler login
# 这会打开浏览器进行授权
3. 创建项目
# 创建新的 Workers 项目
wrangler init my-worker
# 选择项目类型
# - TypeScript (推荐)
# - JavaScript
部署 Next.js 到 Cloudflare Pages
1. 安装依赖
npm install --save-dev @cloudflare/next-on-pages
2. 配置 next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
// 静态导出模式
output: 'export',
// 图片优化配置
images: {
unoptimized: true, // Cloudflare Pages 不支持动态图片优化
},
// 尾部斜杠
trailingSlash: true,
}
module.exports = nextConfig
3. 添加构建脚本
{
"scripts": {
"dev": "next dev",
"build": "next build",
"pages:build": "npx @cloudflare/next-on-pages",
"pages:deploy": "npm run pages:build && wrangler pages deploy .vercel/output/static",
"pages:dev": "npx wrangler pages dev .vercel/output/static --compatibility-flag=nodejs_compat"
}
}
4. 构建和部署
# 构建项目
npm run pages:build
# 部署到 Cloudflare Pages
npm run pages:deploy
# 或者一步完成
npm run pages:deploy
Workers 基础开发
1. 简单的 Hello World
// src/index.ts
export default {
async fetch(request: Request): Promise<Response> {
return new Response('Hello from Cloudflare Workers!', {
headers: {
'content-type': 'text/plain',
},
})
},
}
2. 处理不同的 HTTP 方法
export default {
async fetch(request: Request): Promise<Response> {
const { method, url } = request
const { pathname } = new URL(url)
// 路由处理
if (pathname === '/api/users') {
switch (method) {
case 'GET':
return handleGetUsers()
case 'POST':
return handleCreateUser(request)
default:
return new Response('Method not allowed', { status: 405 })
}
}
return new Response('Not found', { status: 404 })
},
}
async function handleGetUsers(): Promise<Response> {
const users = [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' },
]
return new Response(JSON.stringify(users), {
headers: {
'content-type': 'application/json',
},
})
}
async function handleCreateUser(request: Request): Promise<Response> {
const body = await request.json()
// 验证数据
if (!body.name) {
return new Response('Name is required', { status: 400 })
}
// 创建用户(这里只是示例)
const newUser = {
id: Date.now(),
name: body.name,
}
return new Response(JSON.stringify(newUser), {
status: 201,
headers: {
'content-type': 'application/json',
},
})
}
3. 使用 KV 存储
// wrangler.toml
// [[kv_namespaces]]
// binding = "MY_KV"
// id = "your-kv-namespace-id"
interface Env {
MY_KV: KVNamespace
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const { pathname } = new URL(request.url)
if (pathname === '/api/cache') {
// 读取缓存
const cached = await env.MY_KV.get('my-key')
if (cached) {
return new Response(cached)
}
// 生成新数据
const data = { timestamp: Date.now() }
const value = JSON.stringify(data)
// 写入缓存(TTL: 1小时)
await env.MY_KV.put('my-key', value, {
expirationTtl: 3600,
})
return new Response(value)
}
return new Response('Not found', { status: 404 })
},
}
性能优化技巧
1. 使用缓存 API
export default {
async fetch(request: Request): Promise<Response> {
const cache = caches.default
const cacheKey = new Request(request.url, request)
// 尝试从缓存读取
let response = await cache.match(cacheKey)
if (!response) {
// 缓存未命中,获取新数据
response = await fetch('https://api.example.com/data')
// 克隆响应并缓存
response = new Response(response.body, response)
response.headers.set('Cache-Control', 'max-age=3600')
// 存入缓存
await cache.put(cacheKey, response.clone())
}
return response
},
}
2. 边缘 SSR
// 在边缘渲染 HTML
export default {
async fetch(request: Request): Promise<Response> {
const data = await fetchData()
const html = `
<!DOCTYPE html>
<html>
<head>
<title>边缘 SSR</title>
</head>
<body>
<h1>数据:${data.title}</h1>
<p>${data.content}</p>
</body>
</html>
`
return new Response(html, {
headers: {
'content-type': 'text/html;charset=UTF-8',
},
})
},
}
async function fetchData() {
// 从数据库或 API 获取数据
return {
title: '示例标题',
content: '示例内容',
}
}
3. 请求合并
// 合并多个 API 请求
export default {
async fetch(request: Request): Promise<Response> {
// 并行请求多个 API
const [users, posts, comments] = await Promise.all([
fetch('https://api.example.com/users'),
fetch('https://api.example.com/posts'),
fetch('https://api.example.com/comments'),
])
const data = {
users: await users.json(),
posts: await posts.json(),
comments: await comments.json(),
}
return new Response(JSON.stringify(data), {
headers: {
'content-type': 'application/json',
},
})
},
}
安全最佳实践
1. CORS 配置
function corsHeaders(origin: string) {
return {
'Access-Control-Allow-Origin': origin,
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400',
}
}
export default {
async fetch(request: Request): Promise<Response> {
const origin = request.headers.get('Origin') || '*'
// 处理 OPTIONS 预检请求
if (request.method === 'OPTIONS') {
return new Response(null, {
headers: corsHeaders(origin),
})
}
// 处理实际请求
const response = await handleRequest(request)
// 添加 CORS 头
Object.entries(corsHeaders(origin)).forEach(([key, value]) => {
response.headers.set(key, value)
})
return response
},
}
2. 速率限制
interface Env {
RATE_LIMITER: KVNamespace
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const ip = request.headers.get('CF-Connecting-IP') || 'unknown'
const key = `rate-limit:${ip}`
// 获取当前请求次数
const count = await env.RATE_LIMITER.get(key)
const currentCount = count ? parseInt(count) : 0
// 检查是否超过限制(每分钟 60 次)
if (currentCount >= 60) {
return new Response('Too many requests', {
status: 429,
headers: {
'Retry-After': '60',
},
})
}
// 增加计数
await env.RATE_LIMITER.put(key, (currentCount + 1).toString(), {
expirationTtl: 60, // 1 分钟后过期
})
// 处理请求
return new Response('OK')
},
}
3. 环境变量和密钥
# wrangler.toml
[vars]
ENVIRONMENT = "production"
# 敏感信息使用 secrets
# wrangler secret put API_KEY
interface Env {
ENVIRONMENT: string
API_KEY: string
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// 使用环境变量
console.log(`Environment: ${env.ENVIRONMENT}`)
// 使用密钥
const response = await fetch('https://api.example.com/data', {
headers: {
'Authorization': `Bearer ${env.API_KEY}`,
},
})
return response
},
}
监控和调试
1. 日志记录
export default {
async fetch(request: Request): Promise<Response> {
const start = Date.now()
try {
const response = await handleRequest(request)
// 记录成功请求
console.log({
method: request.method,
url: request.url,
status: response.status,
duration: Date.now() - start,
})
return response
} catch (error) {
// 记录错误
console.error({
method: request.method,
url: request.url,
error: error.message,
duration: Date.now() - start,
})
return new Response('Internal Server Error', { status: 500 })
}
},
}
2. 本地开发
# 启动本地开发服务器
wrangler dev
# 指定端口
wrangler dev --port 8787
# 启用远程模式(使用真实的 KV 等资源)
wrangler dev --remote
3. 查看日志
# 实时查看生产环境日志
wrangler tail
# 查看特定 Worker 的日志
wrangler tail my-worker
常见问题
1. 请求大小限制
Workers 有以下限制:
- 请求体大小:最大 100 MB
- 响应体大小:无限制
- CPU 时间:最大 50ms(免费版)/ 30s(付费版)
2. 不支持的 Node.js API
Workers 运行在 V8 引擎上,不支持所有 Node.js API。使用兼容的替代方案:
// ❌ 不支持
import fs from 'fs'
// ✅ 使用 Web API
const response = await fetch('https://example.com/file.txt')
const text = await response.text()
3. 冷启动优化
虽然 Workers 没有传统意义的冷启动,但首次请求可能稍慢:
// 预加载数据
let cachedData: any = null
export default {
async fetch(request: Request): Promise<Response> {
if (!cachedData) {
cachedData = await loadData()
}
return new Response(JSON.stringify(cachedData))
},
}
总结
Cloudflare Workers 为我们提供了强大的边缘计算能力。关键要点:
- 充分利用边缘网络,减少延迟
- 合理使用缓存,提升性能
- 注意资源限制,优化代码
- 重视安全配置,保护应用
- 做好监控日志,快速定位问题
通过这些实践,你将能够构建出高性能、全球可用的应用。
相关资源
标签: #Cloudflare #Workers #边缘计算 #部署 #性能优化
发布日期: 2025-02-05
作者: 君知博客团队