周三下午,又一次 CI 構(gòu)建因?yàn)槌瑫r(shí)而失敗。日志里那一行 tsc --pretty 固執(zhí)地跑了兩分鐘,接著再花一分鐘把 TypeScript 轉(zhuǎn)成 JavaScript,然后才慢悠悠地把控制權(quán)交給 Webpack。整個(gè)流水線像被按了慢放鍵,每次部署都在排隊(duì)。
大多數(shù) TypeScript 構(gòu)建問題的根源,來自一個(gè)根本性的混淆:團(tuán)隊(duì)把 TypeScript 編譯器既當(dāng)類型檢查器,又當(dāng)構(gòu)建工具用,而它本應(yīng)只做前者。
![]()
傳統(tǒng)立場很堅(jiān)定:一個(gè)工具干完所有活才叫省事。 用 tsc 完成類型檢查并自動生成 JS,然后直接交給打包器,這條順序流水線看上去清晰可控。很多人覺得反正類型檢查總要跑,順便把代碼轉(zhuǎn)譯了也沒什么額外開銷。于是,tsc 輸出文件成了 CI 的必選項(xiàng),每部署一次就要吞噬兩三分鐘。
但真實(shí)情況是,類型驗(yàn)證和代碼生成在邏輯上毫無依賴關(guān)系。TypeScript 編譯器完全可以在不寫任何輸出文件的情況下完成全量類型分析,這就是 --noEmit 做的事情。它讓 tsc 照樣讀每一個(gè)文件、解析導(dǎo)入、檢查賦值、報(bào)告錯(cuò)誤,卻直接跳過生成階段。這一跳,通常能砍掉 40%–60% 的執(zhí)行時(shí)間——因?yàn)楸闅v AST 進(jìn)行類型檢查遠(yuǎn)比做轉(zhuǎn)換和文件 I/O 快得多。
反方觀點(diǎn)很明確:類型檢查和代碼生成應(yīng)該徹底解耦。 打包器(esbuild、webpack、Rollup 或 swc)不需要等待 TypeScript 結(jié)束,只要 CI 一開始就可以并行轉(zhuǎn)譯源文件。兩者同時(shí)跑,構(gòu)建在較慢的那個(gè)任務(wù)結(jié)束時(shí)完成。實(shí)踐中,轉(zhuǎn)譯總是先完成,因?yàn)楝F(xiàn)代打包器根本不負(fù)責(zé)類型檢查。這條新型流水線把阻塞點(diǎn)移除了,實(shí)測構(gòu)建速度提升 60%–80%,而類型安全性完全不變。
具體的配置也極其簡單。在 tsconfig.json 里設(shè)置 "noEmit": true,配合 "strict": true、"target": "ES2022"、"module": "ESNext" 和 "moduleResolution": "bundler"。這個(gè) bundler 模式是 TypeScript 6.0 的模塊解析策略,它假定打包器會接管導(dǎo)入解析,編譯器只負(fù)責(zé)校驗(yàn)類型。運(yùn)行 tsc 后,它立即退出,零輸出。
TypeScript 6.0 的原生執(zhí)行模型更進(jìn)一步改變了規(guī)則。編譯器不再需要為本地開發(fā)生成中間 JavaScript,現(xiàn)代打包器直接剝離 .ts 文件中的類型注解。這使得 tsc 可以聚焦在它最擅長的事情上:驗(yàn)證類型。生產(chǎn)構(gòu)建從此徹底不再觸碰 TypeScript 編譯器的輸出邏輯。
我的判斷是:那個(gè)靠 tsc 輸出文件的日子該結(jié)束了。把 tsc 當(dāng)作構(gòu)建工具就是在往流水線里塞進(jìn)一個(gè)不必要的阻塞器。每等待一秒,部署隊(duì)列里的時(shí)間成本都在累積。遷移到類型檢查與代碼生成并行的模式,代價(jià)只是調(diào)整一下配置,回報(bào)卻是讓 CI 釋放出被鎖死的速度。對于任何期望加快發(fā)布節(jié)奏的團(tuán)隊(duì),這都不是一個(gè)可選項(xiàng),而是一項(xiàng)基礎(chǔ)重構(gòu)。
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.