Next.js 靜態匯出深度解析:如何建構 200+ 頁面的高效能工具站
技术架构(更新於 2026年5月17日)
靜態匯出的核心原理
Next.js 的 output: "export" 模式將整個應用程式預先渲染為純靜態 HTML,無需 Node.js 執行環境:
next build (SSG)
↓
遍歷所有 generateStaticParams()
↓
為每個 [locale] × [slug] 組合預先渲染 HTML
↓
輸出到 out/ 目錄
↓
上傳到 OSS/CDN
SSG vs SSR vs ISR
| 模式 | 需要伺服器 | 建置時渲染 | 更新方式 | 適用場景 |
|---|---|---|---|---|
| SSG (export) | 不需要 | ✅ | 重新建置部署 | 內容固定的工具站 |
| SSR | 需要 | ❌ | 每次請求渲染 | 個人化內容 |
| ISR | 需要 | ✅ | 背景增量重新渲染 | 頻繁更新的內容 |
工具庫選擇 SSG 的理由:
- 200+ 工具頁內容完全靜態,無需動態資料
- 部署到阿里雲 OSS + CDN,零維運成本
- 首屏 TTFB 極低(CDN 直接回傳 HTML)
- 天然支援離線快取
generateStaticParams 的設計模式
多語言 × 工具頁的笛卡兒積
// src/app/[locale]/layout.tsx
export function generateStaticParams() {
return [
{ locale: 'zh-CN' },
{ locale: 'zh-TW' },
{ locale: 'en' },
{ locale: 'ja' },
];
}
// src/app/[locale]/pdf/merge/page.tsx
export function generateStaticParams() {
return [
{ locale: 'zh-CN' },
{ locale: 'zh-TW' },
{ locale: 'en' },
{ locale: 'ja' },
];
}
Next.js 會自動計算 layout.generateStaticParams × page.generateStaticParams 的笛卡兒積,為每個 (locale, path) 組合產生 HTML。
動態路由:部落格文章的列舉
// src/app/[locale]/blog/[slug]/page.tsx
export function generateStaticParams() {
return getStaticParamsForAllPosts().map(({ slug, locale }) => ({
locale,
slug,
}));
}
getStaticParamsForAllPosts() 掃描 src/content/blog/ 目錄,列舉所有 slug × 可用語言,確保每篇文章的每個語言版本都被預先渲染。
建置效能最佳化
工具庫的建置挑戰
- 292 個工具頁 × 4 語言 = 1168 個 HTML 頁面
- 加上部落格、分類頁等,總計 1300+ 靜態頁面
- 每個頁面需要
getTranslations()載入 i18n 訊息
並行控制
// next.config.ts
experimental: {
staticGenerationRetryCount: 2,
...(isCi
? {
staticGenerationMaxConcurrency: 4, // CI: 4 並行
staticGenerationMinPagesPerWorker: 32, // 每 worker 32 頁
}
: {
staticGenerationMaxConcurrency: 16, // 本機: 16 並行
staticGenerationMinPagesPerWorker: 8,
}),
}
- CI 環境:GitHub Actions 記憶體有限,壓低並行避免 OOM
- 本機開發:拉高並行加速建置
逾時設定
staticPageGenerationTimeout: 180, // 3 分鐘
部分工具頁(如影片工具)載入 WASM 相依較多,預先渲染耗時可能超過預設 60s。
多語言路由架構
next-intl + App Router 整合
src/i18n/routing-config.ts
→ locales: ['zh-CN', 'zh-TW', 'en', 'ja']
→ localePrefix: 'always' ← 所有 URL 帶語言前綴
→ localeDetection: true ← Accept-Language 自動協商
URL 結構
https://www.toolsku.com/zh-CN/pdf/merge/ ← 簡體中文
https://www.toolsku.com/en/pdf/merge/ ← 英文
https://www.toolsku.com/zh-CN/blog/pdf-merge-guide/ ← 部落格
hreflang 實作
每個頁面都注入完整的 hreflang 標籤:
<link rel="alternate" hreflang="zh-CN" href="https://www.toolsku.com/zh-CN/pdf/merge/" />
<link rel="alternate" hreflang="zh-TW" href="https://www.toolsku.com/zh-TW/pdf/merge/" />
<link rel="alternate" hreflang="en" href="https://www.toolsku.com/en/pdf/merge/" />
<link rel="alternate" hreflang="ja" href="https://www.toolsku.com/ja/pdf/merge/" />
<link rel="alternate" hreflang="x-default" href="https://www.toolsku.com/zh-CN/pdf/merge/" />
Sitemap 自動探索
工具庫的 sitemap.ts 使用檔案系統掃描自動探索所有頁面:
const pathEntries = discoverLocaleInnerPathsWithFilePath(appDir);
// 自動探索 src/app/[locale]/ 下的所有 page.tsx
跳過動態路由
discoverLocaleInnerPaths 設計上跳過動態段(如 [slug]),因為它們需要參數才能渲染。
對於部落格文章,sitemap.ts 額外處理:
const blogSlugs = getAllBlogSlugs();
for (const slug of blogSlugs) {
entries.push({
url: absoluteLocalizedUrl(locale, `/blog/${slug}`),
lastModified: meta.updatedAt,
priority: 0.7,
alternates: { languages },
});
}
CDN 部署架構
資源前綴 (Asset Prefix)
// next.config.ts
assetPrefix: getAssetPrefix(),
// → 生產環境指向 https://toolsku.oss-cn-beijing.aliyuncs.com/public
建置產物中 _next/static/ 下的 JS/CSS 檔案都指向 CDN,HTML 由 OSS 直接服務。
部署流程
next build → out/
↓
ossutil cp out/ oss://toolsku/ --recursive
↓
CDN 自動重新整理(或等待 TTL)
↓
新版本上線
快取策略
| 資源類型 | 快取策略 | 理由 |
|---|---|---|
_next/static/**/*.js |
Cache-Control: max-age=31536000, immutable | 檔名含 hash |
*.html |
Cache-Control: max-age=3600, s-maxage=86400 | 頁面可能更新 |
*.wasm |
Cache-Control: max-age=31536000 | WASM 版本穩定 |
i18n/*.json |
Cache-Control: max-age=86400 | 搜尋索引定期更新 |
建置流水線
yarn build
→ generate-tools-search-index.mjs ← 產生工具搜尋索引
→ generate-tool-clients-public.mjs ← 產生工具用戶端資料
→ next build ← SSG 預先渲染所有頁面
→ 遍歷 generateStaticParams()
→ 渲染每個 (locale, path) 組合
→ 輸出到 out/
增量建置的挑戰
Next.js 靜態匯出目前不支援增量建置——每次 next build 都會重新渲染所有頁面。對於 1300+ 頁面的專案,完整建置需要 3-5 分鐘。
因應策略:
- CI 環境壓低並行減少記憶體峰值
- 本機開發使用
dev模式(按需渲染,不預先產生) - Turbopack 加速開發模式
經驗總結
| 決策 | 選擇 | 理由 |
|---|---|---|
| 渲染模式 | SSG (export) | 零維運、極低 TTFB |
| 路由模式 | App Router | Server Components、更好的程式碼分割 |
| 國際化 | next-intl | App Router 原生支援、完善的訊息系統 |
| 內容管理 | 程式碼倉庫 (JSON/TS) | 無 CMS 相依、Git 版本控制 |
| 部署 | OSS + CDN | 國內存取快、零維運 |
純靜態匯出是工具類網站的最佳選擇——內容固定、存取頻繁、需要極致的首屏速度。Next.js App Router + SSG 的組合,讓工具庫實現了零伺服器維運下的高效能部署。
本站提供瀏覽器本地工具,免註冊即可試用 →
#Next.js#SSG#静态导出#CDN#性能优化