# Next.js Standalone 模式下 static assets not found 問題解決 ## 前言 在使用 Next.js 時,出於**輕量化部署**或**提升可攜帶性**的考量,不少人會選擇將 `output` 設定為 `standalone`。 然而,在我第一次以 standalone 模式完成建置並啟動服務後,卻發現頁面顯示異常:樣式錯亂、資料缺失,整體看起來就像支離破碎的頁面 下意識按下 **F12** 開啟開發者工具,切換到 **Network tab**,映入眼簾的是一整片 **404 Not Found** 的請求列表,幾乎所有靜態資源都載入失敗  這篇文章記錄了這個問題產生的原因,以及在不使用 CDN 的前提下,如何快速解決 ## 原因 在 Network tab 中檢查失敗的請求後,可以發現這些 404 幾乎全部指向同一個路徑前綴:`_next/static` 進一步查找資料後,我在 Next.js 的一個 Pull Request 中找到了明確說明: [All static assets (js/css/media) in Standalone mode become 404](https://github.com/vercel/next.js/pull/72432) 其中提到: > This minimal server does not copy the `public` or `.next/static` folders by default as these should ideally be handled by a CDN instead. 也就是說,**standalone 模式下產生的 server.js 本質上是一個「最小化的 Node.js Server」**,它的設計目標並沒有提供完整的靜態資源服務 在官方的設想中: - `public` 與 `.next/static` **應交由 CDN 處理** - standalone server 只負責 SSR 與 API 邏輯 - 因此建置時不會自動複製靜態資源 這也正是為什麼在 standalone 模式下直接啟動服務時,所有指向 `_next/static` 的請求都會回傳 404 不過在實際情境中,無論是本地開發階段,或第一次嘗試 standalone 部署時,大多數人**並不會事先準備 CDN**,也很容易忽略這層設計前提,於是就踩進了這個坑。 ## 解決方法 ### 方法一:直接複製靜態資源 (最簡單) 如果暫時不考慮使用 CDN,最直接的解決方式就是: **手動將 `public` 與 `.next/static` 複製到 standalone 的輸出資料夾中**。 官方文件中也明確給出了做法: ```bash cp -r public .next/standalone/ && cp -r .next/static .next/standalone/.next/ ``` ### 方法二:使用 CDN(官方推薦方向) 既然官方明確提到,理想情況下靜態資源應由 CDN 提供,那也可以順著這個設計方向來進行設定。 一個直覺上的疑問是: Next.js 預設請求靜態資源的路徑為:`http://localhost:3000/_next/static/*` 如果改用 CDN,總不可能仍然從相同的網域載入吧? 這點其實在官方文件的 [next.config.js assetPrefix - Set up a CDN](https://nextjs.org/docs/app/api-reference/config/next-config-js/assetPrefix#set-up-a-cdn) 有提及 透過設定 assetPrefix,可以讓 Next.js 在 production 模式下,將所有靜態資源請求導向指定的 CDN 網域,例如: ```js= // @ts-check import { PHASE_DEVELOPMENT_SERVER } from 'next/constants' export default (phase) => { const isDev = phase === PHASE_DEVELOPMENT_SERVER /** * @type {import('next').NextConfig} */ const nextConfig = { assetPrefix: isDev ? undefined : 'https://cdn.mydomain.com', } return nextConfig } ``` 如此一來,就會讓原本的 request: ```text /_next/static/chunks/4b9b41aaa062cbbfeff4add70f256968c51ece5d.4d708494b3aed70c04f ``` 變成: ```text https://cdn.mydomain.com/_next/static/chunks/4b9b41aaa062cbbfeff4add70f256968c51ece5d.4d708494b3aed70c04f0.js ``` ## 參考資料 - [All static assets (js/css/media) in Standalone mode become 404](https://github.com/vercel/next.js/pull/72432) - [docs(output): update standalone docs with cp and start commands](https://github.com/vercel/next.js/pull/72432) - [next.config.js assetPrefix - Set up a CDN](https://nextjs.org/docs/app/api-reference/config/next-config-js/assetPrefix#set-up-a-cdn)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up