Deno 入门教程 / 第 15 章:部署
第 15 章:部署
15.1 部署方案概览
| 方案 | 说明 | 适用场景 |
|---|
| Deno Deploy | 官方托管平台 | Web 应用、API |
| VPS / 云服务器 | 传统部署 | 完整控制 |
| Docker | 容器化部署 | 企业环境 |
| Vercel | 边缘部署 | Fresh 应用 |
| Cloudflare Workers | 边缘函数 | 全球分发 |
15.2 Deno Deploy
什么是 Deno Deploy?
Deno Deploy 是 Deno 官方的云托管平台,特点:
| 特性 | 说明 |
|---|
| 全球分布 | 35+ 个边缘节点 |
| 冷启动 | ~10ms |
| 自动扩展 | 无需配置 |
| 内置 KV | 全球分布式键值存储 |
| GitHub 集成 | 推送即部署 |
| 免费额度 | 100K 请求/天 |
创建项目
# 方法 1:通过网页
# 1. 访问 https://dash.deno.com
# 2. 登录 GitHub 账号
# 3. 创建新项目并关联仓库
# 方法 2:使用 deployctl CLI
deployctl deploy --project=my-app main.ts
项目入口
// main.ts — Deno Deploy 入口
Deno.serve((req) => {
const url = new URL(req.url);
if (url.pathname === "/") {
return new Response("Hello from Deno Deploy!", {
headers: { "content-type": "text/html; charset=utf-8" },
});
}
if (url.pathname === "/api/time") {
return Response.json({
time: new Date().toISOString(),
region: Deno.env.get("DENO_REGION") || "unknown",
});
}
return new Response("Not Found", { status: 404 });
});
环境变量
// 读取环境变量
const dbUrl = Deno.env.get("DATABASE_URL");
const apiKey = Deno.env.get("API_KEY");
// 在 Deno Deploy 控制台中设置环境变量
// Settings → Environment Variables
部署 Fresh 应用
# Fresh 项目结构
deno.json —— 依赖配置
main.ts —— 入口文件(由 Fresh 自动生成)
# 部署步骤:
# 1. 推送到 GitHub
# 2. 在 Deno Deploy 关联仓库
# 3. 入口文件设置为 main.ts
# 4. 自动部署
15.3 Deno KV(云端)
创建 KV 数据库
// 在 Deno Deploy 中使用 KV
const kv = await Deno.openKv();
// 基本操作
await kv.set(["users", "alice"], { name: "Alice", age: 30 });
const { value } = await kv.get(["users", "alice"]);
console.log(value);
KV 实战:缓存层
class CacheManager {
#kv: Deno.Kv;
constructor(kv: Deno.Kv) {
this.#kv = kv;
}
async get<T>(key: string[]): Promise<T | null> {
const entry = await this.#kv.get<T>(key);
return entry.value;
}
async set<T>(key: string[], value: T, ttlMs?: number): Promise<void> {
const options: Deno.KvSetOptions = {};
if (ttlMs) {
options.expireIn = ttlMs;
}
await this.#kv.set(key, value, options);
}
async getOrFetch<T>(
key: string[],
fetcher: () => Promise<T>,
ttlMs: number = 60 * 60 * 1000 // 1 hour default
): Promise<T> {
const cached = await this.get<T>(key);
if (cached !== null) return cached;
const fresh = await fetcher();
await this.set(key, fresh, ttlMs);
return fresh;
}
}
// 使用
const kv = await Deno.openKv();
const cache = new CacheManager(kv);
// 自动缓存 API 响应
const users = await cache.getOrFetch(
["api", "users"],
() => fetch("https://api.example.com/users").then(r => r.json()),
5 * 60 * 1000 // 5 分钟缓存
);
15.4 边缘计算
边缘函数的优势
用户请求 → 边缘节点(最近) → 直接响应
↓
不需要回源到中央服务器
延迟极低,体验更好
边缘函数示例
// A/B 测试
Deno.serve((req) => {
const cookie = req.headers.get("cookie") || "";
const isNewUser = !cookie.includes("visited=true");
const response = new Response(
isNewUser ? "欢迎新用户!" : "欢迎回来!"
);
response.headers.append("Set-Cookie", "visited=true; Path=/; Max-Age=86400");
return response;
});
// 地理位置路由
Deno.serve((req) => {
const country = req.headers.get("x-vercel-ip-country") || "unknown";
const city = req.headers.get("x-vercel-ip-city") || "unknown";
return Response.json({ country, city });
});
15.5 VPS 部署
使用 systemd 管理服务
# /etc/systemd/system/my-deno-app.service
[Unit]
Description=My Deno App
After=network.target
[Service]
Type=simple
User=deno
ExecStart=/usr/local/bin/deno run --allow-net --allow-env main.ts
Restart=always
RestartSec=5
Environment=DENO_DIR=/home/deno/.cache/deno
WorkingDirectory=/home/deno/app
[Install]
WantedBy=multi-user.target
# 启用并启动服务
sudo systemctl enable my-deno-app
sudo systemctl start my-deno-app
# 查看日志
sudo journalctl -u my-deno-app -f
Nginx 反向代理
# /etc/nginx/sites-available/my-deno-app
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
15.6 本章小结
| 方案 | 优势 | 劣势 |
|---|
| Deno Deploy | 免费、全球分发、冷启动快 | 运行时限制 |
| VPS | 完全控制 | 需要运维 |
| Docker | 可移植 | 配置复杂 |
📖 扩展阅读
下一章:第 16 章:npm 兼容性 → 深入了解 Deno 的 npm 兼容方案。