iT邦幫忙

2026 iThome 鐵人賽

DAY 29
0
Software Development

30天打造一套企業PLM系列 第 29

Day 29:部署上線——前端靜態資源封裝、外部設定與 SPA 快取

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20260915/20161290sDQZLWMBWW.jpg

系列:30 天打造企業級 PLM|面向:全端|素材:部署腳本、版本機制實作

問題場景

開發環境跑得好好的,上線那天的清單卻長得嚇人:機密設定不能進版控、SPA 的快取策略沒想好會讓使用者拿舊前端打新 API、資料庫 migration 在生產環境只有一次機會,還要準備萬一不行怎麼退。

更麻煩的是上線這件事本身沒有練習場。前 28 天的每個決定都可以改、可以重跑、可以在本機重來;上線那天你面對的是一份真資料、一群正在等著開單的使用者,和一個「兩小時內修不好就要回退」的倒數。今天把最後一哩路走完。

商業邏輯設計

  • 切換日由營運日曆決定:避開結案潮與盤點期。技術上任何週末都能上,業務上只有某幾個週末能上。這條看似瑣碎,但排錯日子的代價是整個團隊在最忙的那週同時處理上線問題與業務催單
  • 雙軌期與回退方案是業務承諾。舊系統唯讀保留多久、什麼條件觸發回退(核心動線壞且兩小時內修不好),這些要在上線前白紙黑字。出事當下所有人都在壓力下,那不是討論「要不要回退」的好時機——決策標準要在冷靜的時候先寫好
  • 使用者培訓與公告節奏:系統再好,沒人會用就是失敗的上線。What's New 機制(Day 22)在此接棒日常溝通

技術選型與取捨

架構演進:從 WebLogic 多層式 Domain 到單一產物極簡部署

以前部署一套 Oracle Agile PLM,是一場耗資巨大且極端繁瑣的工程:

  1. 多層式伺服器陣列:必須在多台專屬伺服器上規劃 WebLogic Domain,包括 AdminServer、ManagedServer 節點叢集、NodeManager 守護處理序、獨立的 Tomcat File Manager 檔案庫,以及後端的 Oracle RAC 資料庫,硬體與維護成本高昂;
  2. 安裝與升級極度沉重:每次升級要跑耗時數小時的安裝精靈、手動同步多節點 EAR、校驗 Java 版本與系統環境變數,容錯率極低。

這個架構最大的隱性成本不是硬體,是**「不敢動」**:每次升級都是一場動員,於是升級間隔越拉越長,安全補丁越積越多,最後變成不升級的惡性循環。

Mini-PLM 採用單一產物交付(Single Artifact)與輕量化部署架構:前端 build 出來的純靜態資產在打包時直接複製進後端 static 目錄,由 Spring Boot 統一託管提供 Web 服務與 REST API,組態外置,一個 WAR/JAR 檔即可搞定全系統部署,幾秒內完成冷啟動。

https://ithelp.ithome.com.tw/upload/images/20260915/20161290gacC2OlXTU.png

圖的左半是建置管線,右半是這個選擇換來的三件事。要特別注意中間那條橘色虛線:機密不在產物裡,是啟動時才從伺服器本機疊上去的。這條線決定了同一個 WAR 檔可以原封不動地部到測試與生產——兩個環境的差異全部關在外部檔裡,而不是關在兩份不同的建置產物裡。

部署形態:前端靜態資源封裝進後端

Day 2 的打包架構在此兌現:前端 npm run build 產物由腳本複製到後端靜態資源目錄(static/),與後端一起打包成單一 WAR。伺服器直接承載 SPA 路由與 REST API:

  1. 零 CORS 與路徑統一:靜態檔與 REST API 端點都在同一個 host 與 port 下,完全不需要設定跨來源資源共享(CORS),也不需要額外維護 Nginx 反向代理;
  2. 極致簡化維運:部署只需要更新一個 WAR/JAR 檔,備份、重啟與版控單純清晰。回退就是把上一版的檔案換回去,不需要記得「還有哪幾個地方要一起退」;
  3. 無狀態與擴展空間:後端採用 JWT 無狀態認證(Day 6)且無本機狀態依賴(檔案走集中儲存,Day 25),未來若需要多台節點掛載負載平衡器(LB),每一台節點都能獨立以完整功能提供服務。

取捨要說清楚:前後端綁在同一個產物裡,代表只改前端一行字也要重新打包整包。以我們的節奏(一週一次到兩次發布)這個成本可以接受,換來的是「部署單位只有一個」的維運單純度。如果團隊大到前後端要獨立發布節奏,這個選擇就該重新評估。

機密外部配置

生產環境的 datasource URL、密碼放外部配置檔(伺服器本機路徑,Spring 啟動時疊加載入),版控與封裝檔裡只有無害的預設值。理由有三:

  • 機密不進 git 歷史:進了就洗不掉。git filter-branch 洗得掉檔案,洗不掉已經 clone 出去的那幾份
  • 同一個封裝檔可部到任何環境:測試與生產的差異全在外部檔,「測試環境測過的就是生產要跑的那個檔」這句話才成立
  • DBA 換密碼不需要重新打包:改檔、重啟,結束

資料庫 migration 的生產紀律

Flyway 在生產的規矩(Day 27 的延伸):

  1. 上線前先在生產資料的複本跑過一輪 migration,時間與鎖表行為都要量過。開發機上 0.2 秒的 ALTER TABLE,在三百萬列的生產表上可能是十分鐘的鎖表
  2. 上線時 migration 先行於新版程式,順序顛倒會讓新程式打到舊 schema
  3. 絕不手動改 flyway_schema_history,出問題走 flyway repair 或開新版修正

第三條是血淚:手改歷史表是把小事故升級成大事故的標準路徑,因為改完之後資料庫的實際狀態與紀錄不再一致,之後每一次 migration 都建立在一個謊言上。

核心內容:SPA 快取策略——三種資源三種待遇

SPA 上線後最陰的問題:使用者停在舊版前端打新版 API。瀏覽器快取著上週的 JS,而 API 契約這週改了,各種詭異錯誤只有特定幾個使用者遇得到,重現不能——你在自己的機器上怎麼點都是對的,因為你的快取是新的。

解法是把資源分三類各給策略:

資源 快取策略 理由
hash 資產(index-a1b2c3.js immutable 長快取 檔名含內容 hash,內容變了檔名就變,舊檔永遠正確地舊著
index.html 不快取(no-cache) 它是指向 hash 資產的指標,必須每次拿最新
version.json 不快取 + 前端輪詢 版本偵測通道

https://ithelp.ithome.com.tw/upload/images/20260915/20161290Waccvoc4md.png

這張圖上半的三張卡只有一個邏輯:快取期限該由「這個檔會不會變」決定。hash 資產永遠不會變(變了就是另一個檔名),所以可以無限期快取;index.html 每次發布都會變(指向新的 hash),所以完全不能快取。搞混這兩者的方向,就是 SPA 快取事故的全部成因。

下半的迴圈是承認現實:使用者永遠有辦法停在舊版,筆電闔蓋一週再打開就是了。version.json 配前端的新版通知橫幅——build 時寫入版本號(Day 2 打包腳本的 Step 0),前端定期比對,伺服器版本比手上新就顯示「新版本已發布,請重新整理」。與其保證他不會舊,不如保證他知道自己舊了。

搭配的防線是 vendor chunk 紀律(Day 2):改動 chunking 必跑生產驗證腳本。白畫面事故的絕大多數,都是快取策略與 chunk 結構的組合技——單獨看每一邊都沒問題,湊在一起就是使用者拿著舊的 index.html 去要一個已經不存在的 chunk。

上線檢查清單(實際版本的骨架)

□ 生產複本上 migration 演練通過(含耗時紀錄)
□ 外部配置檔就位、無版控殘留機密
□ health check 通(/actuator/health——只答自己,Day 22)
□ 煙霧測試:登入 → 開單 → 簽核 → 放行(核心動線,人工或 E2E smoke)
□ version.json 版本正確、What's New 內容就緒
□ 回退預案:上一版封裝檔在手、migration 回退腳本或相容性確認
□ 監控頁開著(Day 22)、第一小時盯著錯誤指紋

這份清單的設計原則是:每一項都要能在上線前就得到明確的是或否,不能有「應該沒問題」。「回退預案」那一項尤其——上一版的 WAR 檔實際放在哪個路徑,要打得出來,不是「應該還在 build server 上」。

踩坑記錄

  • 外部配置檔漏項:新功能加了設定鍵,生產的外部檔沒跟著補。啟動失敗還算好的,最怕靜默用了預設值——系統跑起來了,行為卻不是你以為的那個。緩解:設定鍵有新增就進上線清單,關鍵設定缺值時 fail fast 不給預設。寧可起不來,也不要帶著錯誤設定起來
  • Tomcat log 編碼:Windows 加 Tomcat 的 console 編碼與 UTF-8 log 檔的組合,中文 log 變亂碼。判定編碼問題要驗 codepoint,不能憑畫面下結論——CP950 終端機顯示 UTF-8 本來就長得像亂碼,檔案本身可能完全正常。曾經為此追過一輪不存在的 bug

小結

前端靜態資源封裝單一產物交付、機密外部化、migration 生產紀律、SPA 快取三分法加版本偵測。

上線這件事的技術含量其實不高,難的是把所有「應該沒問題」換成「我剛剛確認過」。30 天的建造到此完工。明日 Day 30:總結回顧、踩坑排行榜、未來的 AI 藍圖,以及一點心路歷程。


上一篇
Day 28:資安強化實戰——帳號鎖定、授權補洞與攻擊面盤點
系列文
30天打造一套企業PLM29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言