iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0

「防災平台不只是程式碼的集合,更是一套能穩定運行的生命線。」

在前面的篇章裡,我們談過願景、使用者研究、清單架構、AI 模組與 UX 優化。
今天要跨入一個對所有Side Project都至關重要的議題:
如何把專案從「我的電腦」帶到「所有人的日常」。

這就是部署(Deployment),以及更進一步的持續整合與持續交付(CI/CD)。


一、為什麼部署如此關鍵?

防災資訊的價值,在於「即時」與「可用」。

  • 即時: 颱風預警、地震速報、物資更新,必須能立刻反映。
  • 可用: 任何人,不管是在手機或電腦上,都能快速開啟,無需安裝、無需繁瑣設定。

對「韌性生活指南」專案而言,部署不只是技術手段,而是 將防災知識轉化為全民可用工具的最後一哩路


二、部署架構選擇:Vercel × MongoDB Atlas

為什麼選擇這個組合?

  1. Vercel:專為前端而生的部署平台
  • 自動化 CI/CD: GitHub 推送 → 自動編譯 → 自動上線。
  • Edge Network: 快速全球分發,確保使用者不因地理位置卡住。
  • 適合 Next.js: 前端程式碼幾乎零設定即可部署。
  1. MongoDB Atlas:雲端資料庫服務
  • 高可用性: 自動備援,確保資料在斷電或災害中依然有副本。
  • 水平擴展: 使用者增加時,資料庫能無痛擴容。
  • 安全性: 內建加密與存取控制,符合防災資訊應有的資安規範。
    這樣的組合,讓Side Project 能在短時間內擁有接近「企業級」的穩定性。

三、CI/CD 流程設計

  1. 開發到部署的自動
  • Commit: 開發者將程式碼推送到 GitHub。
  • Build: Vercel 偵測到更新,自動建置最新版本。
  • Deploy: 測試通過後,自動發佈到正式環境。
  1. 測試與驗證
  • 單元測試 (Unit Test): 確保推薦邏輯不會因小改動而失效。
  • 端對端測試 (E2E): 模擬使用者填寫問卷、生成清單的完整流程。
  • 安全檢查 (Security Check): 避免因錯誤設定導致資料外洩。
  1. 回滾機制
  • 若部署後出現錯誤,Vercel 可一鍵回滾到上一個穩定版本,避免服務中斷。

四、跨平台使用體驗

對一般使用者來說,他們不會在意 CI/CD 的細節,但會直接感受到:
1.手機/電腦同步: 不論在哪個裝置打開,都是最新版本。
2.快速回應: 清單生成與電商串接,不因伺服器延遲而卡頓。
3.穩定可靠: 颱風來襲、同時多人使用,也不會崩潰。
這正呼應了 「韌性生活指南」的願景:穩定而堅韌的日常


五、PM的推動策略

1.短期:

  • 建立最小可行 CI/CD 流程,確保每次推送都能自動更新。
  • 設定基礎安全規則(API 金鑰保護、DB 權限分層)。

2.中期:

  • 建立自動測試套件,涵蓋 AI 推薦與 UX 問卷流程。
  • 新功能先部署到 Staging,測試後再進正式環境。

3.長期:

  • 擴展多地節點,讓資料能在台灣、日本、美國都有備份。
  • 整合更多外部 API(如氣象局、災防告警系統),真正做到動態更新。

六、結語

部署不是專案的「最後一步」,而是 專案能不能真正被使用的起點

從 GitHub 的程式碼,到 Vercel 的自動化部署,再到 MongoDB Atlas 的安全儲存,每一環都在回答一個問題:
「在災難發生時,這個平台能不能即時、可靠地幫助到使用者?」

這就是 CI/CD 在「韌性生活指南」專案中的價值:
讓技術不只是存在於工程師的世界,而是成為每個家庭的守護者。


補充:Vercel × MongoDB Atlas:實戰執行步驟

0) 專案預備(本機)

1.建立專案與套件

npx create-next-app@latest resilient-kit --ts --eslint
cd resilient-kit
npm i mongodb mongoose zod @tanstack/react-query
npm i -D vitest @testing-library/react playwright @playwright/test

2.建立基本目錄

/app           # Next.js App Router
/app/api/**    # API route handlers (Server Actions / Route handlers)
/lib/db.ts     # 連線池與DB工具
/models/**     # Mongoose schemas
/tests/**      # 單元/端對端測試
/scripts/**    # seeding、維運腳本

DoD: 專案可在本機 npm run dev 啟動,首頁可見。


1) 建立 MongoDB Atlas 叢集與安全設定

1.建立專案與叢集

  • Region:選 Asia Pacific (Tokyo/Seoul/Singapore) 就近台灣使用者。
  • Tier:M10 起(可先 M0 測試,流量上來再升級)。

2.建立資料庫使用者(最小權限)

  • 建立 app_user 僅賦予讀寫應用資料庫(例:resilient_kit)。

3.IP 存取

  • Development 先加你本機 IP;上線後改用 Vercel egress IP
    (或先開 0.0.0.0/0 但不建議)。

4.連線字串

  • 取得 MONGODB_URI,格式:
mongodb+srv://app_user:<PASSWORD>@cluster0.xxxxx.mongodb.net/resilient_kit?retryWrites=true&w=majority

5.資料模型(範例)

// /models/Item.ts
import { Schema, model, models } from "mongoose";
const ItemSchema = new Schema({
  name: { type: String, required: true },
  category: { type: String, enum: ["必備","情境","選配"], required: true },
  expiresInDays: Number,
  tags: [String]
}, { timestamps: true });
export default models.Item ?? model("Item", ItemSchema);

DoD: 可由本機成功連線 Atlas,CRUD 正常;DB 使用者權限最小化。


2) 在程式中實作 DB 連線與健康檢查

1.連線工具

// /lib/db.ts
import mongoose from "mongoose";

const MONGODB_URI = process.env.MONGODB_URI!;
if (!MONGODB_URI) throw new Error("Missing MONGODB_URI");

let isConnected = 0 as 0|1;

export async function connectDB() {
  if (isConnected) return;
  await mongoose.connect(MONGODB_URI, { dbName: "resilient_kit" });
  isConnected = 1;
}

2.健康檢查API

// /app/api/health/route.ts
import { NextResponse } from "next/server";
import mongoose from "mongoose";
export async function GET() {
  const state = mongoose.connection.readyState; // 1 = connected
  return NextResponse.json({ ok: state === 1, state });
}

DoD:/api/health回傳 { ok: true }


3) GitHub 版本庫與分支策略

1.建立GitHub Repo ,推送本機程式碼。
2.分支保護

  • main:受保護,需 PR 並通過測試。
  • dev:開發整合分支。
    3.必須檢查
  • 要求 PR 至少 1 個 reviewer
  • 必須通過 CI(單元+E2E)。
    **DoD:**分支保護規則生效;PR 未通過測試不可合併。

Vercel 專案設定(環境+多階段)

1.Import GitHub Repo 到Vercel。

2.建立環境

  • Production:main
  • Preview: PR就會生成預覽網址
  • Development: 本機

3.環境變數(在 Vercel Project → Settings → Environment Variables)

  • MONGODB_URI(Prod/Preview 各自設定)
  • OPENAI_API_KEY(如用 AI 模組)
  • NEXT_PUBLIC_BASE_URL(可選)

4.Build 指令

  • Framework:Next.js(Vercel 會自動識別)
  • Build Command:next build
  • Output:.vercel/output(自動)
    DoD:推 PR 可自動生成 Preview;合併 main 自動部署 Production。

5) CI:自動化測試(Vitest / Playwright)

1.加入 Vitest(單元測試)

// package.json
"scripts": {
  "test": "vitest run",
  "test:ui": "vitest"
}

  • 撰寫範例
// /tests/unit/recommender.test.ts
import { describe, it, expect } from "vitest";
import { recommend } from "@/lib/recommender";
describe("recommender", () => {
  it("returns essentials by default", () => {
    const res = recommend({ people: 1 });
    expect(res.essentials.length).toBeGreaterThan(0);
  });
});

2.加入 Playwright(E2E)

npx playwright install

// /tests/e2e/basic.spec.ts
import { test, expect } from "@playwright/test";
test("能生成清單", async ({ page }) => {
  await page.goto(process.env.PREVIEW_URL ?? "http://localhost:3000");
  await page.getByLabel("家中人數").selectOption("3");
  await page.getByRole("button", { name: "產生清單" }).click();
  await expect(page.getByText("你的專屬清單")).toBeVisible();
});

3.GitHub Actions(可選)
若你要在 GitHub 跑測試(再交由 Vercel 部署):

# .github/workflows/ci.yml
name: CI
on:
  pull_request:
  push:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - run: npm ci
      - run: npm run test
      - run: npx playwright install --with-deps
      - run: npx playwright test

DoD: PR會自動執行單元+E2E 測試;測試不過不可合併。


6) 資安與機敏資訊治理

1.環境變數只放在 Vercel ,不進 Git。
2.API金鑰保護: 伺服器端 Route Handlers(不要在 client 暴露機密)。
3.CORS/Rate Limit (可選):防止濫用 API。
4.Mongo 資安

  • 僅 app_user 有資料庫讀寫權
  • 不使用 root 使用者
  • 啟用 SCRAM 認證與 傳輸加密 (Atlas 預設)。
    5.日誌與稽核
  • Vercel Logs + Atlas Atlas Auditing(付費 tiers)
  • 設告警(連線峰值、錯誤率)
    DoD: repo 無金鑰;Production 僅 server 端可讀敏感變數;資料庫帳密最小權限。

7) Staging/Production 雙環境

1.Atlas建立兩個DB: resilient_kit_dev / resilient_kit_prod
2.**Vercel設兩組 ** MONGODB_URI(Preview 用 dev、Production 用 prod)。
3.資料種子腳本(選用)

# /scripts/seed.ts
# 以 ts-node 執行,注入必備/情境/選配範例

DoD: Preview 永遠不會污染 Production 資料;測試人員可在預覽站自由玩。


8) 定時任務(提醒有效期/補貨)

Vercel 無常駐 Cron,可用 Vercel Cron(Beta)或外部 Scheduler(如 GitHub Actions、Railway)。

1.建立提醒 API

// /app/api/cron/expire-check/route.ts
import { NextResponse } from "next/server";
import { connectDB } from "@/lib/db";
import Item from "@/models/Item";
export async function GET() {
  await connectDB();
  // 查即將到期的物資,發通知(Email/LINE)
  // ...
  return NextResponse.json({ ok: true });
}

2.設定排程 (Vercel → Settings → Cron Jobs)

  • 0 3 * * * 觸發 GET https://your.app/api/cron/expire-check
    **DoD:**每日自動檢查;可在 Logs 看到 Cron 執行紀錄。

9) 觀測性(Observability)

1.指標

  • 可用性:鋪設 /api/health 探針
  • 使用:PV/UV、清單產生成功率
  • 轉化:電商連結點擊率
  • 可靠:錯誤率、95/99% 響應時間

2.工具

  • Vercel Analytics(基礎)
  • Log aggregation(Sentry/Logtail/Datadog 任選)

3.告警

  • Health endpoint 非 200
  • 錯誤率 > 阈值(例如 2%)
  • DB 連線超過上限
    DoD:關鍵異常 10 分鐘內可知悉;能追溯錯誤來源。

10) 回滾與熱修(Incident Playbook)

1.回滾

  • Vercel → Deployments → Revert to this deployment
    2.熱修流程
  • 建 hotfix 分支 → 修正 → PR → 合併 main → 自動部署
    3.事後檢討(簡版RCA)
  • 事件時間線/影響範圍/根因/修正與防再發
    DoD: 出事 10 分鐘內可切回穩定;48 小時內完成 RCA。

11) 使用者隱私與法規(精要)

  • 隱私權政策與使用條款(首頁 Footer 必備)
  • 個資最小化: 能匿名就匿名(人數、情境即可,不必收姓名)
  • 資料保存策略: 到期自動刪除/匿名化
  • 取得告知同意: Email 通知、LINE 綁定需明確同意
    DoD: 法遵頁面可見;後端保留刪除/匿名化腳本。

12) 發佈前「一頁式檢核清單」(貼牆版)

  • [ ] /api/health:OK
  • [ ] Preview 與 Prod 使用不同 DB
  • [ ] .env 無提交到 Git
  • [ ] PR 測試必過(unit + E2E)
  • [ ] Cron 提醒可執行
  • [ ] 觀測告警已設定
  • [ ] 隱私權政策/使用條款可見
  • [ ] 回滾驗證過一次
  • [ ] README 有「本地啟動/部署說明」

常見錯誤 & 快速修復

  • Atlas 連線失敗: 多半是 IP 白名單或 dbName 未設/帳密錯。
  • Preview 能跑、Prod 掛掉: 通常是環境變數漏填或權限不同步。
  • Vercel 冷啟動延遲: 把高頻 API 用 Edge Functions 或快取。
  • E2E 測試在 CI 不穩: 為測試專設測資與固定假資料;加 awaitpage.waitFor...

小結

嘗試照這份手冊走,把 「韌性生活指南」 從可執行的程式,推到 可用、可維運、可持續迭代 的服務。
當使用者在颱風夜打開網站、三分鐘拿到專屬清單並完成採買時——這一整條 CI/CD 與部署鏈,就真正轉化成了 社會的韌性


上一篇
Day17|UX優化落地策略
下一篇
Day19|測試與調整:從 Debug 到 Usability Test
系列文
《韌性生活指南:用科技打造更堅韌的日常》24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言