matterlabo docs
04 部署與基礎設施

04 Next.js Pages Router 靜態輸出部署注意事項

Pages Router 靜態輸出專案的部署路徑、資產路徑與驗收提醒。

這份文件給接手 Chlitina-RefiningKindShare-Exocare 的人看。兩個站都是 Next.js Pages Router 靜態輸出,但路徑處理方式不一樣;排查時如果把 basePathassetPrefix、build 後補寫混成同一件事,很容易越修越亂。

先說結論:這類專案最常壞的不是頁面 component,而是輸出後的公開路徑。首頁能開,不代表 _next chunk、圖片、SVG、字型也會在實際部署位置正常載入。驗收時一定要直接打 deployed URL,重新整理一次,再看 Network。

單一 repo 的 build 指令、env 名稱與檔案位置,仍以 repo README 為準。這份文件只整理跨專案共通的部署風險。

敏感資料交付提醒:本文件中的 0505-environment-variables05-environment-variables_環境變數與金鑰;該文件含 env value / secret 線索,僅做本地交付,不做雲端交付。

什麼時候看這份

如果你現在處理的是 build command、套件安裝或單一 repo 的 script,先看 repo README。如果問題和部署後的 URL、子目錄、資產 404、字型失效有關,才回到這份。

情境先看哪裡
剛接手,不確定專案是不是 Pages Router 靜態輸出先看下方 適用專案
某一站 build 失敗該 repo README
deploy path、hosting、rollback 權限不清楚04 Deployment Guide
env 值、env 開關或缺值症狀不清楚05-environment-variables
reload 後停在舊 scroll 位置,首屏動畫、ScrollTrigger 或鎖滾動流程錯亂09 的 scroll restoration 初始化防護文件
字型有載入,但 macOS / Retina 上看起來比 Figma 粗09 的 Figma 字重與瀏覽器顯示差異文件

適用專案

Project路徑策略接手時先讀
Chlitina-Refiningoutput: "export",並依 env 切換 distDir / basePathrepo README -> 這份 -> 05
KindShare-ExocareassetPrefix="./",再用 build 後腳本補寫 CSS 裡的字型路徑repo README -> 這份 -> 05

這兩個站都不是一般 SSR 專案。不要用「server 起來就好」的方式驗收,也不要只檢查 out/ 或輸出資料夾有沒有生成。靜態輸出真正要驗的是:這包檔案被放到正式位置後,瀏覽器能不能用正確路徑找到所有資產。

先判斷是哪一型問題

你看到的症狀先懷疑
首頁能開,但 /_next/ chunk、CSS、圖片 404basePathassetPrefix 或部署子目錄對不上
站內點擊正常,重新整理 deployed URL 後壞掉export 後路徑假設錯誤,或 hosting 子目錄沒有對齊
畫面大致正常,但字型退回 fallback fontCSS 裡的字型路徑沒有被補寫,或相對層級錯了
只改 env 開關,整包靜態檔的公開路徑跟著變該 env 不只控制 UI,也影響輸出目錄或公開 URL 前綴
字型已載入,但和 Figma 粗細不同這多半是瀏覽器與作業系統渲染差異,回 09 的字重文件

這裡有一個很實用的分界:404 是部署輸出問題;字看起來比較粗,不一定是部署壞掉。先用 Network 把字型檔是否真的載入確認清楚,會省很多時間。

共通規則

  • 不要假設正式站一定掛在網域根目錄 /
  • 不要把 Pages Router 靜態輸出專案當成 SSR 專案排查。
  • 新增站內連結時,優先交給 Next 路由或站內絕對路徑,不要手刻 ./about../about 這類相對路徑。
  • 新增圖片、SVG、字型等資產時,先確認它是由 Next 接管,還是 build 後仍要額外補寫。
  • 驗收時要直接打 deployed URL 並重新整理,不要只靠站內點擊。
  • 頁面如果有 GSAP ScrollTrigger、首屏動畫或鎖滾動流程,reload 驗收時也要確認瀏覽器沒有沿用舊 scroll 位置。

Chlitina-Refining

這個站最需要記的是:表單開關、輸出資料夾、公開 URL 前綴是綁在一起的。NEXT_PUBLIC_SHOW_FORM_SECTION 不只控制畫面上某個 section 顯示與否,也會影響 distDir 名稱;ENV_VAR=production 時,basePath 會跟著輸出資料夾名稱走。

所以排查時不要只問「這次表單要不要開」。也要一起確認這次 build 會輸出到哪個資料夾,以及部署後使用者實際打開的 URL 前綴是不是同一個。

新增路徑或資產時,避免在 JSX 裡手寫 ./foo.png../foo.png./about。圖片優先 import 後交給 next/image 或專案既有的包裝元件處理。這樣做不是為了風格一致而已,而是讓 basePath 有機會正確接管公開路徑。

常見誤判:

  • 以為只是開關某個 section,實際上部署目錄也一起變了。
  • 以為 basePath 是補救相對路徑的工具,實際上它是公開 URL 前綴設定。
  • 只在 local dev 驗證,沒有用正式子目錄 URL 打開 deployed 版本。

KindShare-Exocare

這個站的重點不同。正式 build 會靠 ENV_VAR=productionassetPrefix="./" 生效;它可以處理 Next 自己產出的靜態資源,但不會自動修正 CSS 裡硬寫的字型路徑。

因此 replace-in-file --configFile=config.js 不是可有可無的整理腳本,而是正式 build 鏈的一部分。少了它,頁面可能看起來有出來,_next 也不一定壞,但字型會在非 root path 部署時退回 fallback font。這種問題很容易被誤判成設計稿、瀏覽器或字重設定差異。

驗收時除了看 out/ 是否生成,也要打開實際部署位置,確認 Network 裡的字型檔不是 404,畫面也沒有掉到 fallback font。

常見誤判:

  • 以為有 output: "export"assetPrefix,所有資源就都會自動相對化。
  • 以為 replace-in-file 可以刪,結果只在非 root path 部署時才發現字型壞掉。
  • 只檢查輸出資料夾,沒有在實際部署 URL 驗字型與 _next 資產。

最少驗收清單

  1. 直接輸入 deployed URL,重新整理後頁面仍然正常。
  2. Network 沒有 404/_next/ chunk、圖片、SVG、字型。
  3. 如果這次有改 env,確認 build 用的是哪組輸出目錄與公開 URL 前綴。
  4. 如果專案有 build 後補寫腳本,確認腳本真的跑完,輸出檔內容也已被改寫。
  5. 如果頁面有首屏動畫、ScrollTrigger 或鎖滾動流程,reload 後再看一次首屏狀態。

和其他文件怎麼搭配

On this page