beio Logobeio

【Cloudflare Workers 全端架構師之路 02】入門篇:開發環境與 Hono 框架最佳實踐

發布於

01. 前言:別再用 Express 寫 Workers

在 Part 1 中,我們理解了 Edge 的架構優勢。現在我們要開始寫程式碼了。

很多從 Node.js 轉過來的開發者,第一直覺是:「我能不能用 Express.js?」 答案是:可以,但不建議。

Express 是為傳統 Node.js runtime 設計的,它依賴許多 Node.js 特有的 API (http, stream 等) 且體積相對臃腫。在追求極致輕量與啟動速度的 Edge 環境,我們需要一個原生支援 Web Standards (Fetch API) 的框架。

這就是為什麼 Cloudflare 官方與社群一致推薦 Hono

02. 環境建置:Wrangler CLI

Wrangler 是 Cloudflare 的官方瑞士軍刀。它負責了從專案建立、本地模擬 (基於 workerd runtime) 到全球部署的所有工作。

確保你的 Node.js 版本 >= 18.0.0,然後執行:

# 使用 Hono 官方模板初始化專案
# 選擇項目:
# - Template: cloudflare-workers
# - Do you want to install project dependencies? Yes
# - Which package manager do you want to use? npm
npm create hono@latest my-edge-api

進入目錄後,你會看到 wrangler.toml。這是整個專案的控制中心,相當於 K8s 的 yaml 檔或 AWS 的 SAM template。

03. 深度解析:Hono vs. Express

為什麼說 Hono 是架構首選?讓我們看程式碼對比:

🔴 Express (Node.js 思維)

const express = require('express');
const app = express();

// 依賴 Node.js 的 Request/Response 物件
app.get('/', (req, res) => {
  // req.headers 是 Node 特有的物件結構
  res.json({ message: 'Hello' });
});
// 體積大,冷啟動稍慢,不完全相容 Cloudflare Types

🟢 Hono (Edge 思維)

import { Hono } from 'hono'
const app = new Hono()

// 使用標準 Web API
app.get('/', (c) => {
  // c.req 封裝了標準 Request 物件
  // c.env 提供完美的型別推斷 (TypeScript Friendly)
  return c.json({ message: 'Hello' })
})
// 體積 < 14kB,專為 Cloudflare Workers 優化,0ms 冷啟動

架構師觀點: Hono 的 API 設計幾乎複製了 Express (路由、Middleware),讓團隊學習曲線降到最低,但底層完全貼合 V8 Isolates 特性。

04. 實戰:環境變數管理 (Configuration Management)

在企業級應用中,我們絕對不能把 API Key 硬編碼 (Hardcode) 在程式裡。Cloudflare 提供了三層變數管理機制,很多新手容易混淆:

1. wrangler.toml [vars]

適合放非敏感的公開設定(例如:App 名稱、預設語系)。這些值會被 commit 進 Git。

# wrangler.toml
[vars]
APP_NAME = "My Edge API"
API_VERSION = "v1"

2. .dev.vars (本地開發用)

適合放本地開發時的敏感資料(例如:本地資料庫密碼)。必須加入 .gitignore

# .dev.vars
API_SECRET_KEY="local-secret-123"

3. Encrypted Secrets (線上生產用)

適合放線上環境的敏感資料(例如:Stripe Key, Database URL)。這些值不會出現在檔案中,而是加密儲存在 Cloudflare 後台。

# 設定線上變數
npx wrangler secret put API_SECRET_KEY
# (系統會提示你輸入數值)

05. 實作:地理位置識別 API

讓我們整合 Hono 與環境變數,寫一個能識別使用者位置,並讀取設定的 API。

修改 src/index.ts

import { Hono } from 'hono'

// 1. 定義環境變數型別 (TypeScript 的強項)
type Bindings = {
  APP_NAME: string;       // 來自 wrangler.toml
  API_SECRET_KEY: string; // 來自 .dev.vars 或 Secrets
}

// 2. 注入型別
const app = new Hono<{ Bindings: Bindings }>()

app.get('/', (c) => {
  // Cloudflare 特有的地理位置資訊 (在 cf 物件中)
  const location = c.req.raw.cf;
  
  // 讀取環境變數
  const appName = c.env.APP_NAME;
  
  // 模擬驗證 Secret (在真實 Middleware 中會用到)
  const hasSecret = !!c.env.API_SECRET_KEY;

  return c.json({
    app: appName,
    secure: hasSecret,
    message: `Hello from ${location?.city || 'Localhost'}, ${location?.country || 'Unknown'}!`,
    // 顯示更多地理資訊
    meta: {
      latitude: location?.latitude,
      longitude: location?.longitude,
      timezone: location?.timezone
    }
  })
})

export default app

06. 本地模擬與全球部署

本地開發 (Local Development)

Cloudflare 的本地開發體驗 (DX) 非常優秀。它不依賴 Docker,而是使用 workerd (與線上相同的 runtime) 進行模擬。

npm run dev

按下 b 開啟瀏覽器,你會看到它抓不到 city (因為是 localhost),但能讀到 APP_NAME

部署 (Deployment)

npm run deploy

部署完成後,打開線上的 URL。 找個在國外的朋友(或用 VPN),你會發現 citycountry 準確地顯示了他們的所在地。這就是 Edge 的魔力——無需任何 IP 資料庫查詢,資訊與生俱來

07. 小結與下一步

我們已經建立了一個現代化、型別安全且支援多環境配置的 Edge API 基礎。

但現在我們的 API 是「無狀態」的。每次請求進來都是全新的,它記不住使用者是誰,也無法儲存資料。

在下一篇 Part 3: 設定篇,我們將引入 Cloudflare 的第一個儲存服務 —— Workers KV。 我們將深度比較它與 Redis 的差異(這很重要,別把它當 Redis 用!),並實作一個企業級的多層次快取策略 (Tiered Caching)


Ken Huang

關於作者

Ken Huang

熱衷於嘗試各類新技術的軟體開發者,現階段主力為 Android / iOS 雙平台開發,同時持續深耕前端與後端技術,以成為全端工程師與軟體架構師為目標。

最廣為人知的代表作為 BePTT。開發哲學是「以做身體健康為前提」,致力於在工作與生活平衡的基礎上,打造出擁有絕佳使用體驗的軟體服務。

這裡是用於紀錄與分享開發經驗的空間,希望能透過我的實戰筆記,幫助開發者解決疑難雜症並提升效率。

Android APP DevelopmentiOS APP DevelopmentBePTT CreatorFull Stack Learner