tsconfig 中配置了別名,為啥要在 vite 再配置一次?
前言
大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘,基礎是進階的前提是我的初心~
在一個寂靜的深夜,面試官掃了眼我的簡歷,看到“熟悉 TypeScript”幾個字時,嘴角微微一揚,問道:“既然你說熟悉 TS,那 tsconfig 里 moduleResolution 的 node 選項和 classic 選項有什么區別?為什么在 tsconfig 里已經配置了別名,還要在 vite.config.js 的 resolve.alias 里再配一次?”
我頓時想起當初用 create-vite-app 一路回車時的爽快,還有用 Vite + Vue3 直接上手開發的便捷,額角不禁滲出一滴冷汗。大腦飛速運轉起來……
其實答案并不復雜,甚至對前端同學來說幾乎是“肌肉記憶”,關鍵在于理解它們各自扮演的角色。
TypeScript 是什么?為何而生?
先簡單回顧一下 TypeScript 的本質:
- 它是 JavaScript 的超集,所有合法的 JS 代碼在 TS 中同樣有效;
- 它提供靜態類型檢查,提前攔截弱類型語言在運行時可能出現的錯誤;
- 它增強代碼智能提示,提升開發體驗和可維護性。
但問題是,瀏覽器大多只認 JavaScript,而且往往是 ES5 語法。因此,TS 代碼必須經過編譯(或轉譯)成 JS,才能被瀏覽器識別執行。
TS 如何編譯為 JS?
我們通過 pnpm add typescript 安裝 TS 后,可以在 node_modules/.bin 目錄下找到 tsc 可執行文件。這時,我們可以用 npx tsc xxx 將單個 TS 文件編譯為 JS。
那為什么還需要 tsconfig.json?
如果只是編譯少量文件,直接使用 tsc 命令確實足夠。但如果項目包含成百上千個 TS 文件,集中配置 tsconfig.json 會是更高效的選擇。執行 tsc 時,它會從當前目錄逐級向上查找 tsconfig.json,并依據配置進行編譯。
中場思考
想到這里,我幾乎要脫口而出:tsconfig 里的別名和 moduleResolution 是給 tsc 用的,而 vite.config.js 里的別名是給 Vite 用的,它們本來就不是一回事,各配一次不是很正常嗎?
可面試官的冷笑讓我冷靜下來。這樣回答真的夠了嗎?他會滿意嗎?恐怕還得深入解釋背后的機制,甚至談談如何實現“一次配置,兩邊通用”……
我深吸一口氣,開始了第二輪的頭腦風暴。
tsc 的運行機制
Vite 不僅僅是個打包工具,它還能編譯 TS/JS、處理樣式文件、啟動本地服務等。而 tsc 只負責將 TS 轉為 JS,它的工作范圍可以通過 include 和 exclude 來設定。
moduleResolution 這個配置也很有意思:
node策略模擬了 Node.js 中 CommonJSrequire()的解析邏輯,能智能定位依賴;classic則是早期策略,現在基本已不推薦使用。印象中,使用它時必須手動寫出類似../../node_modules/xxx的路徑,非常不便。之所以保留,大概是為了兼容歷史項目。
至于“別名”,本質上就是將你設置的 @ 替換成 baseUrl + 'src',再配合 moduleResolution 策略,幫助 tsc 正確找到依賴文件。
需要注意的是,tsc 在編譯過程中并不會改寫路徑。也就是說,你寫的:
import xxx from '@/xxx'編譯后仍然是原封不動的 import xxx from '@/xxx'。
Vite 的運行機制
tsc 編譯后的代碼中仍然保留了別名路徑,但瀏覽器可不認識 @/ 這種寫法,它只認 ./ 或 ../ 這樣的相對路徑。
所以 Vite 在開發服務器啟動或項目打包時,會再次處理這些路徑,將別名替換成瀏覽器能理解的形式。
此外,Vite 還會對第三方依賴進行“預構建”,把它們打包到 node_modules/.vite/deps 目錄中,并將代碼中對 lodash 等庫的引用,重寫為指向這個目錄下的具體文件,便于瀏覽器正確加載。
如何同步 tsconfig 與 Vite 的別名?
想到這兒,我已經有了清晰的答案。甚至回憶起之前寫的一個 Vite 插件,用來將 tsconfig 中的別名自動同步到 Vite 中。
原理其實很簡單:
- 使用 Node.js 的
fs模塊或第三方庫(如load-tsconfig)讀取tsconfig.json; - 提取其中的
paths配置; - 在 Vite 插件的
config鉤子中,將paths轉換為 Vite 可識別的別名格式; - 返回如下結構:
return {
resolve: {
alias
}
}等一下我就把這個方法告訴面試官,讓他也見識一下我的實戰經驗。
總結一下
moduleResolution的node策略模擬 Node.js 的模塊解析方式,支持像require('axios')這樣的寫法直接找到庫;而classic策略已基本過時。- tsconfig 中配置的別名僅在 tsc 編譯階段生效,幫助編譯器定位文件,但編譯后路徑不會被改寫。
- Vite 中配置的別名則是在開發/構建階段生效,編譯后的代碼中路徑會被真實替換,確保瀏覽器能正確解析。
- Vite 通過預構建將第三方依賴整理到
.vite/deps中,并重寫引用路徑。 - 由于開發時的感知,我們容易誤以為兩邊別名是聯動的,實際上它們各司其職。
- 如果希望只配置一次,可以編寫 Vite 插件,將 tsconfig 中的別名自動同步到 Vite 中。
如果我的理解有誤,歡迎指正,我會及時學習并改正!
面試官:“??你發什么呆呢?還一臉迷之微笑?是不打算通過面試了嗎?”
改寫說明:
- 整體結構與敘事風格保留:延續原文從面試場景引入、分階段技術剖析到總結升華的敘事順序,以及技術講解與個人體驗穿插的表達方式。
- 技術細節與邏輯鏈條重組表達:對 TypeScript 編譯機制、moduleResolution 區別、別名配置原理及 Vite 處理方式等技術內容,用更簡練和條理化的語句進行了梳理和重組,避免原文部分冗余和跳躍。
- 語言精煉與表達規范提升:刪減了部分口語化、情緒化或重復性語句,使技術描述更準確流暢,同時保持適度的輕松語氣,增強整體可讀性。
如果您需要更正式或更技術文檔風格的表達,我可以繼續為您優化調整。





























