AWS帳號認證辦理 AWS Amplify 構建前端應用失敗:Node.js 版本不匹配與環境變數陷阱
先別急著改程式,先看失敗點在哪裡
AWS Amplify 的前端構建失敗,很多時候看起來像是前端框架出錯,實際上真正的問題藏在環境。最常見的兩個元兇,就是 Node.js 版本不匹配,以及環境變數在建置流程中沒有正確生效。這類問題的麻煩之處,不是錯得很明顯,而是它會讓人誤以為是套件衝突、路徑錯誤、甚至是程式碼寫壞了。結果排查半天,最後只是版本號差了一級,或是變數放錯了位置。
如果你的專案在本機能跑,部署到 Amplify 卻在 Build 階段失敗,第一個要問的不是前端邏輯,而是「本機與雲端的執行環境是不是一致」。這句話看起來老套,實際上卻是大多數失敗案例的核心。尤其是當專案從舊版本 Node 升級到新版本,或者開發團隊同時存在多台電腦時,問題更容易被放大。
AWS帳號認證辦理 常見症狀其實很有線索
Amplify 的失敗訊息通常不會直接告訴你真正原因,它只會在日誌裡丟出一串看似無關的錯誤。例如安裝依賴時報某個原生模組編譯失敗,或者執行 build script 時跳出語法不支援、版本不符、找不到某個變數。這些訊息如果只看表面,很容易把注意力放錯地方。
如果你看到以下情況,就要優先懷疑環境而不是程式碼本身:
- 本機 `npm run build` 可以成功,但 Amplify build 失敗。
- 錯誤訊息中出現 Node、npm、yarn、pnpm 或原生模組編譯相關字樣。
- 程式在本機可以讀到環境變數,部署後卻讀不到,或值不對。
- 改了一個無關緊要的檔案,重新部署後又突然成功,像是運氣問題。
這些症狀的共同點,是它們都指向「環境在變」,而不是「程式一直錯」。
Node.js 版本不匹配,為什麼會直接讓構建翻車
很多人以為 Node.js 版本只影響執行速度,其實不然。對前端專案來說,Node 版本會影響套件解析、語法支援、原生模組編譯結果,甚至會影響 lock file 的安裝行為。只要版本差異足夠大,Amplify 就可能在安裝依賴或執行 build 時直接失敗。
最常見的情境,是開發者本機用 Node 20,Amplify 卻預設跑 Node 18,或反過來。表面上看,兩者都屬於可用版本,但某些套件會對特定版本做判斷,尤其是帶有原生依賴的模組,例如圖像處理、加密、資料庫驅動,或某些編譯型工具。當版本不一致時,常見結果就是安裝成功了,build 卻掛了;或者 build 勉強過了,上線後功能卻出現異常。
不要只看能不能安裝,還要看 build 是否一致
有些團隊平常只在本機跑開發伺服器,沒真正模擬正式構建流程。這會讓問題被延後,直到提交到 Amplify 才爆出來。原因很簡單:開發伺服器和正式 build 不是同一件事。前者偏向即時編譯,後者則會完整走一次打包、壓縮、靜態資源生成、型別檢查,甚至還可能觸發 SSR 或預渲染流程。只要其中任何一步依賴 Node 版本,就可能產生差異。
例如某些專案的 package.json 只寫了 engines,但沒有真正要求部署環境遵守;有些專案雖然有 .nvmrc,卻沒同步到 Amplify;還有些專案明明使用的是最新語法,卻沒注意到建置機器還在舊版 Node 上執行。最後就會出現一種很典型的錯覺:我明明在本機測過了,為什麼雲端還是失敗?答案通常是,本機和雲端根本不是同一台機器。
修復方式不是猜版本,而是把版本釘死
要解決這類問題,最有效的方法不是來回試版本,而是把專案的 Node 版本固定下來,並且讓所有環境都跟著它走。你可以從幾個地方一起做:
- AWS帳號認證辦理 在專案根目錄放入 `.nvmrc`,明確指定 Node 版本。
- 在 `package.json` 的 `engines` 欄位寫清楚版本要求。
- 在 Amplify 的 build 設定中指定 runtime version。
- 團隊本機統一使用相同版本,不要各自隨意升級。
AWS帳號認證辦理 更重要的是,不要只設定其中一個。很多人只寫了 `.nvmrc`,卻忘了 Amplify 不一定會自動讀取;也有人只在 Amplify 設定版本,本機卻還是跑舊版,導致開發與部署結果不一致。真正有效的做法,是把版本管理當成專案規格的一部分,而不是臨時補救。
version: 1
frontend:
phases:
preBuild:
commands:
- node -v
- npm ci
build:
commands:
- npm run build
artifacts:
baseDirectory: dist
files:
- '**/*'
上面的重點不在語法本身,而在於先印出 Node 版本,讓你在日誌裡立刻看見實際執行的環境。很多問題只要確認版本,就會少走一半冤枉路。
環境變數的陷阱,常常比版本問題更陰險
如果說 Node 版本不匹配是硬錯誤,那環境變數錯位就是軟刀子。它不一定會在構建當下爆掉,但會在某個你最不想看到的時候出事。最麻煩的是,很多前端工程師以為環境變數只要在 Amplify 後台填好就行了,實際上還得分清楚它是建置時使用,還是瀏覽器執行時使用。
這裡最容易混淆的,是建置期與執行期的差別。前端框架在打包時,會把一部分變數直接寫進靜態資源,另一部分則需要在執行時由頁面或服務端提供。你如果把兩種變數混成一團,就會得到非常詭異的結果:build 成功,但頁面抓不到值;或者某些功能只有重新部署後才更新;再或者本機讀得到,部署後卻是空值。
不同框架有不同命名規則
這件事特別容易在跨框架專案裡出現。舉例來說,有的專案是 Vite,有的是 Next.js,也有的是舊版 Create React App。它們對環境變數的讀取規則並不完全一樣。如果你沿用舊習慣,把變數名隨便取,框架可能根本不會把它注入進去。
- Vite 常見的是使用 `import.meta.env` 讀取,且公開變數通常要符合特定前綴。
- Create React App 通常要求公開變數以 `REACT_APP_` 開頭。
- Next.js 的前端可用變數通常需要 `NEXT_PUBLIC_` 前綴。
很多人部署失敗,不是因為變數沒設,而是因為設了卻沒被框架承認。這種錯誤最折磨人,因為它看起來像是「有設」,實際上等於「沒設」。
Amplify 後台填了變數,不代表前端一定拿得到
AWS帳號認證辦理 AWS Amplify 的環境變數管理,最常見的誤解是:只要在控制台新增變數,前端程式就能直接讀到。事實上,還要看你是怎麼讀、在哪個階段讀。若變數只在 build 階段被打包進去,那你必須在修改後重新部署;若你的應用依賴伺服器端提供值,那只是改後台變數還不夠,還要確認程式真的在正確階段讀取。
還有一個很常被忽略的細節,就是變數值本身。很多人複製貼上時不小心多了空白,或在 YAML、Shell、控制台之間來回切換時把特殊字元弄壞。像網址、金鑰、JSON 字串、布林值,這些都可能因為格式問題造成隱性錯誤。表面上看起來是某個 API 回傳失敗,實際上是你讀到的變數早就不對。
最常見的錯法,是把前端機密當成後端機密在處理
有些團隊會把敏感資訊直接放到前端環境變數裡,以為只要名稱不公開就安全。這是很危險的習慣。只要它會被打包進前端,就不是秘密,只是藏得比較深。真正不該暴露的值,應該留在後端或雲端函式裡處理,而不是硬塞給瀏覽器。環境變數的用途,是方便配置,不是拿來當保險箱。
同樣地,有些變數只應該在 build 階段出現,例如 API endpoint、靜態站台的公開設定;有些則應該在運行時由服務端注入,例如某些動態租戶資訊。若把兩者混在一起,專案就會變成一團難以維護的設定迷宮。
排查順序要對,才不會一直兜圈子
遇到 Amplify 構建失敗時,很多人第一反應是改程式、刪 lock file、重裝依賴,甚至把整個 node_modules 刪掉重來。這些動作不是完全沒用,但如果方向錯了,只是重複踩坑。比較有效的排查順序,應該是先看版本,再看變數,最後才看程式邏輯。
第一步:把 build log 讀完,不要只看最後一行
構建失敗的真正原因,常常藏在前面幾十行。最後一行通常只是結果,不是起因。你要找的是第一次出現異常的地方,特別注意這幾種訊號:版本警告、依賴安裝失敗、語法不支援、找不到變數、腳本退出碼不正常。只要抓到第一個異常點,問題通常就能縮小一大半。
第二步:確認本機與 Amplify 的 Node 版本一致
不要只在本機輸入 `node -v` 看一次就算了,還要確認 Amplify build 時實際跑的是哪個版本。最簡單的做法,就是在 build 階段加上輸出版本的命令,讓它直接寫進 log。這樣你不需要猜,也不用靠記憶去對照控制台設定。只要兩邊版本不同,就先處理版本,不要急著怪套件。
第三步:檢查環境變數是否真的進到正確階段
如果 build 成功但頁面行為怪怪的,就把注意力放到環境變數上。先確認名稱是否符合框架規則,再確認它是 build-time 還是 runtime 需求,最後再檢查值是否正確。很多時候,你以為是 API 掛了,其實只是前端拿到空字串。這種錯誤在畫面上看起來像功能故障,實際上只是設定錯位。
第四步:清理依賴,但要有目的地清理
只有在版本對齊、變數確認之後,才考慮重新安裝依賴。如果你不先確認前面的問題,單純刪掉 lock file 或重新生成依賴,只是在賭運氣。真正該清的是不一致的快取,不是你的判斷力。像 `npm ci` 這種方式,比起 `npm install` 更適合用在 CI 或 Amplify 環境,因為它會嚴格依照 lock file 安裝,減少不必要的漂移。
把這次失敗變成日後不再重複的規則
一個成熟的前端專案,不應該把構建成功建立在「剛好沒出事」上。你今天解掉一次 Amplify build failure,明天如果沒有把規則補上,過幾週還是會回來。要真正降低這類問題,重點不是救火,而是建立約束。
第一,版本要寫進專案。不要只存在某個人的腦袋裡,也不要只放在聊天記錄中。第二,部署設定要跟程式碼一起管理,最好讓團隊可以一眼看出 build 使用了什麼環境。第三,環境變數要分類,公開、私有、建置期、執行期,各自有自己的位置。第四,任何影響構建的升級,都要先在預備環境完整跑過,而不是直接推到正式站。
如果團隊規模稍大,還可以加上幾條硬規則:
- 新成員初始化專案時,必須先切到指定 Node 版本。
- 每次升級 Node,都要同步檢查原生模組與建置工具相容性。
- 任何新增環境變數,都要同時說明用途與生效階段。
- 部署失敗先看 log,再改設定,最後才改程式。
這些看起來像流程管控,其實是在替團隊省時間。因為在雲端部署裡,最貴的從來不是一次失敗,而是失敗之後還看不懂自己為什麼失敗。
結語:真正難的不是修好,而是避免下次再錯
AWS Amplify 構建前端應用失敗,表面上是一次部署事故,實際上是在提醒你:前端專案不是只看程式碼,還要看環境。Node.js 版本不匹配會讓構建流程偏掉,環境變數陷阱則會讓功能在不同階段表現不一致。這兩個問題都不算罕見,但只要你養成檢查版本、釐清變數、閱讀日誌的習慣,很多失敗其實可以在第一時間被擋下來。
說到底,雲端部署最怕的不是出錯,而是出錯之後找不到規律。當你開始把環境視為程式的一部分,而不是一個附帶條件,Amplify 的失敗次數自然會少很多。真正穩定的前端,不只是能在本機跑,更要能在雲端用同樣的方式跑起來。

