模組二|選型、語言遷移與地基(Day 6–11)
模組二的最後一天,講建置。
先看舊專案的建置指令,一字不差:
vue-cli-service test:unit && vue-cli-service build --max_old_space_size=6144
兩件事值得停下來看。
第一,它要手動指定 6GB 記憶體上限。 不加這個參數,建置會因為記憶體不足而失敗。
第二,建置之前會先跑單元測試。 這看起來是好習慣,但 Day 2 我們數過,這個專案全庫只有一個測試檔。
所以那個 test:unit && 實際上在做的事是:每次建置前,花時間跑一個測試,然後永遠通過。
它不保護任何東西,但沒有人刪掉它。因為刪掉「跑測試」這件事,聽起來就像在降低品質。
先解決第一個問題:為什麼要 6GB?
我把可能的來源盤了一下:
| 來源 | 規模 |
|---|---|
| 四份語言檔 | 合計 15,606 行純物件字面量 |
| 富文本編輯器 | 拆成 20 個子套件手動拼裝 |
| 圖表庫 | 全量引入,沒有按需 |
這三樣加起來,就是那 6GB 的答案。
而其中最諷刺的是語言檔:它不是程式邏輯,是一萬五千行的字典。建置工具沒辦法「聰明地」處理它,只能整包吃進記憶體。(這件事在 Day 22 會有完整的解法。)
舊專案的建置設定檔有 136 行,裡面做了很多「看起來很懂」的優化:
一、把核心套件排除在打包之外。
config.externals({
vue: 'Vue',
'vue-router': 'VueRouter',
vuex: 'Vuex',
axios: 'axios',
'element-ui': 'ELEMENT',
})
意思是「這五個套件不要打包進來,我會用 CDN 從外面載」。這在當年是常見的優化:減少 bundle 體積、利用瀏覽器快取。
二、手動掛了五個外掛:編輯器專用的、壓縮的、清理的、CSS 優化的、程式碼壓縮的。
三、開發代理設定了六個目標位址,其中好幾個是寫死的內網位址,旁邊還帶著同事代號的註解。
這些設定的共同問題不是「做錯了」,問題出在接下來這件事。
老房子的電箱裡有一個沒貼標籤的開關。它一直是開著的。
你想整理電箱,問了所有住過這裡的人,沒有人知道它控制什麼。
你敢關嗎?
不敢。萬一它控制的是消防警報呢?萬一它控制的是隔壁鄰居家的什麼呢?
於是它就一直開著,直到房子拆掉。
那五個外掛、那五個被排除的套件、那六個代理位址,每一個當初都有理由。但六年後,理由死了,設定還活著。
而且更麻煩的是:建置設定壞掉的方式,通常不是報錯,是「某個環境下行為變得不一樣」。所以就算你想驗證「拿掉這個還能不能跑」,你也只能在自己機器上試,沒辦法證明正式環境不會出事。
於是所有人的最佳策略都是:不要碰。
這就是我在 Day 4 講的那句話的另一個版本:技術債不是讓你多寫程式碼,是讓你不敢刪程式碼。
先講數字上的變化:
| 舊(webpack / vue-cli) | 新(Vite) | |
|---|---|---|
| 專案層建置設定 | 136 行 | 39 行 |
| 手動掛的外掛 | 5 個 | 0 個 |
| 手動排除的套件 | 5 個 | 0 個 |
| 硬編在設定檔的位址 | 6 個 | 0 個 |
專案層的設定從 136 行變成 39 行。那些「看起來很專業」的優化全部消失了,不是我們手動拿掉的,是新的建置工具本來就處理好了。
那複雜度跑去哪了?跑到共用的建置套件裡(Day 6 講過我們抽了這個),大約 211 行。
但這是一個關鍵差別:那 211 行有主人。 它是一個獨立的套件、有自己的目錄、被兩個專案共用。你要改它的時候,你知道自己在改什麼、影響誰。
而舊系統那 136 行沒有主人:它躺在專案根目錄,六年來每個人都往裡面加一點東西,沒有人負責整體。
設定檔要像程式碼一樣有主人。沒有主人的設定,三年後就會變成沒人敢碰的黑盒。
我原本以為換完 Vite,那個 6GB 的問題會消失。
我去看了新專案的建置指令:
cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=8192 pnpm vite build
8192。比舊的 6144 還高。
看到這個數字我愣了一下。換了號稱更快的建置工具,記憶體上限反而調高了。
我的理解是:新專案的功能更多了(頁面數比舊的多、語系從 4 個變成 11 個),所以要處理的東西本來就更大。而且正式打包(production build)這件事,Vite 底層還是要做完整的靜態分析和壓縮,它並沒有魔法。
所以要精確地說:
換 Vite 沒有讓「正式打包」變輕鬆,它改變的是別的東西。

我沒有做正式的效能測試(沒有跑對照組、沒有控制變因),所以下面講的是體感,不是數據,這點我要先講清楚。
真正有感的差別在開發伺服器的啟動速度。舊系統要等,新系統幾乎是按下去就好。
這件事為什麼重要?因為它直接影響一個很少被討論的東西:工程師願不願意重跑。
如果重啟一次要等兩分鐘,你會怎麼做?
你會盡量不重啟。改設定的時候用猜的、遇到怪問題先試著繞過去、能不動的地方就不動。
如果重啟只要三秒,你會直接試。
慢的建置不只是浪費時間,它會改變你的工作方式,而且是往壞的方向:更少驗證、更多猜測、更不敢做大膽的嘗試。
這是我認為換建置工具最被低估的收穫。它不會出現在任何效能報告上,但它每天都在影響決策品質。

最後講多環境,這裡也有一個誠實的部分。
新專案有 7 個環境設定檔(開發、測試、正式、容器化、打包分析、本機覆蓋…),建置指令的差別只剩「模式」:
vite build # 正式
vite build --mode test # 測試
vite build --mode docker
比起舊系統把代理位址硬編在建置設定檔裡,這是明顯的進步:環境差異收進了設定檔,建置指令變得一致。
但我打開開發環境的設定檔,看到這個:
VITE_PROXY_URL = https://xxx-admin.example.com
# VITE_PROXY_URL = https://xxx-uat.example.com
切換後端環境,還是靠註解掉另一行。
跟舊系統一模一樣的做法,只是換了個檔案。
我不打算把它說成什麼深刻的道理,它就是一個沒被處理完的小問題。但它很有代表性:重構會解決掉大的結構問題,而那些「不夠痛所以沒人管」的小習慣,會原封不動地跟著搬進新家。
如果你正在做遷移,這類東西值得列一張清單,因為它們單獨看都不值得處理,加起來卻是「新專案為什麼還是有點髒」的答案。
一、建置工具換掉之後,舊的除錯經驗會歸零。 那些「打包出問題時該看哪裡」的直覺要重新建立,而且新工具的錯誤訊息你一開始會看不懂。
二、生態成熟度不同。 有些為舊建置工具寫的外掛,在新工具上沒有對應品,得自己找替代或自己寫。這在遷移初期會卡住幾天。
三、「正式打包」不會變快多少。 如果你的賣點是這個,會失望。要講的話,講開發迴圈。
模組二到這裡結束。我們決定了用什麼、不用什麼、以及哪些地方刻意打折。
明天開始模組三,進入真正的執行:一百個頁面要搬,第一個搬哪個? Day 12 會給一個我覺得整個系列最有意思的發現:同一個團隊做了兩次遷移,第二次故意用了跟第一次完全相反的策略。