TypeScript 路徑設定與 tsconfig.json 路徑相關設定
前言
TypeScript 專案中,模組之間的匯入 (import) 路徑若處理不好,會變成地獄級相對路徑,例如:
1  | import { getUser } from "../../../utils/api";  | 
為了解決這問題,我們需要理解 tsconfig.json 中與「路徑」有關的設定,特別是 baseUrl、paths、rootDir、outDir。
相對路徑與絕對路徑
相對路徑 (relative path)
- 開頭必須是 
./或../ - 代表是以目前檔案的位置為起點
 
1  | // ./ 表示目前目錄  | 
規則表
| 符號 | 意義 | 範例 | 實際對應 | 
|---|---|---|---|
./ | 
目前目錄 | ./utils/math | 
從目前檔案的目錄去找 | 
../ | 
上一層 | ../config | 
從目前檔案往上一層再往下找 | 
../../ | 
上兩層 | ../../types | 
以此類推 | 
若你寫 import x from "./";,代表要匯入目前目錄下的 index.ts 檔案。
絕對路徑 (absolute path)
- 不以 
./或../開頭 - 依照 
baseUrl設定來決定「從哪裡開始找」 - 可搭配 
paths建立路徑別名 (alias) - 如果沒有設定 
baseUrl,TypeScript 會將非相對路徑當作 npm 套件 去node_modules裡找 
例:
1  | import { add } from "utils/math";  | 
如果在 tsconfig.json 中設定 "baseUrl": "./src",那這行就代表:
「請從 src/ 目錄底下去找 utils/math.ts。」
rootDir 與 outDir
1  | {  | 
| 設定 | 功能 | 
|---|---|
rootDir | 
指定原始 TypeScript 檔案的來源資料夾,根據這個設定來決定 outDir 中的檔案相對路徑 | 
outDir | 
指定編譯後 JavaScript 檔案的輸出位置 | 
範例結構:
1  | project/  | 
編譯後:
1  | project/  | 
baseUrl:設定模組搜尋的根
預設情況
TypeScript 會將非相對路徑當作 npm 套件 去 node_modules 裡找,因此:
1  | import { add } from "utils/math";  | 
若沒設定 baseUrl,會報錯「找不到模組」。
正確設定方式
1  | {  | 
效果:
| 匯入語法 | 實際對應檔案 | 
|---|---|
"utils/math" | 
src/utils/math.ts | 
"components/Button" | 
src/components/Button.ts | 
paths:建立路徑別名 (alias)
paths 可搭配 baseUrl 一起使用,讓路徑更語意化、更乾淨。
1  | {  | 
使用方式:
1  | import { Button } from "@components/Button";  | 
對應:
1  | project/  | 
在執行環境中啟用 alias
TypeScript 編譯器知道 alias,但執行環境 (Node.js、Vite、Webpack) 不一定知道。
Vite
1  | // vite.config.ts  | 
vite-tsconfig-paths 會自動讀取你的 tsconfig.json 裡的 "baseUrl" 和 "paths" 設定。
Webpack (需手動設定 resolve.alias)
Webpack 不會自動讀取 tsconfig,所以要在 webpack.config.js (或 .ts) 裡自己指定 alias。
1  | // webpack.config.js  | 
__dirname 表示當前檔案所在的資料夾:/Users/.../project。
path.resolve(__dirname, "src") 表示:/Users/.../project/src。
這樣你就能在專案中這樣寫:
1  | import { Button } from "@components/Button";  | 
Webpack 的 alias 是「執行時期」設定。TypeScript 的 paths 是「編譯時期」設定。它們要同步一致,否則編譯能過、執行會失敗。
Node.js (執行原生 TypeScript 或編譯後 JS)
Node.js 本身不會讀 tsconfig.json,視執行方式不同,使用不同方法。最常使用 tsconfig-paths 套件:
1  | npm i tsconfig-paths -D  | 
在 package.json 修改啟動命令:
1  | {  | 
這樣 Node.js 在執行時會自動解析 tsconfig.json 裡的 alias。
include 與 exclude
控制 TypeScript 要編譯哪些檔案。
1  | {  | 
include:指定要包含的檔案或資料夾 (預設["**/*"])exclude:指定要忽略的檔案或資料夾 (預設["node_modules"])
tsconfig.json 完整範例
1  | {  | 
使用方式:
1  | import { Button } from "@components/Button";  | 
總結
| 設定項目 | 功能 | 範例 | 
|---|---|---|
rootDir | 
原始 TypeScript 檔案的根目錄,決定「結構」 | "src" | 
outDir | 
編譯後 JS 輸出目錄 | "dist" | 
baseUrl | 
import 非相對路徑 module 的搜尋 (解析) 起點 | 
"./src" | 
paths | 
自訂 alias | "@/*": ["*"] | 
include | 
指定要編譯的檔案,決定「範圍」 | "src/**/*" | 
exclude | 
排除不需編譯的檔案,決定「範圍」 | "node_modules" | 
./→ 目前目錄../→ 上一層目錄- 沒有 
./或../→ TypeScript 視為「非相對路徑」,依baseUrl尋找,或當作 npm 套件 去node_modules裡找 - 搭配 
paths可建立語意化的 alias 
參考資料:
TypeScript 官方文件:Module Resolution
Vite 官方文件:vite-tsconfig-paths 外掛