强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

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 兼容方案。