TypeScript基礎入門之模組解析(二)
模組解析
Base URL
使用baseUrl是使用AMD模組載入器的應用程式中的常見做法,其中模組在執行時"deployed"到單個資料夾。
這些模組的原始碼可以存在於不同的目錄中,但構建指令碼會將它們放在一起。
設定baseUrl通知編譯器在哪裡可以找到模組。
假定所有具有非相對名稱的模組匯入都相對於baseUrl
baseUrl的值確定為:
1) baseUrl命令列引數的值(如果給定的路徑是相對的,則根據當前目錄計算)
2) 'tsconfig.json'中baseUrl屬性的值(如果給定的路徑是相對的,則根據'tsconfig.json'的位置計算)
請注意,設定baseUrl不會影響相對模組匯入,因為它們始終相對於匯入檔案進行解析。
您可以在RequireJS和SystemJS文件中找到有關baseUrl的更多文件。
路徑對映(Path mapping)
有時模組不直接位於baseUrl下。
例如,對模組"jquery"的匯入將在執行時轉換為"node_modules/jquery/dist/jquery.slim.min.js"。
載入程式使用對映配置在執行時將模組名稱對映到檔案,請參閱RequireJs文件和SystemJS文件
TypeScript編譯器支援使用tsconfig.json檔案中的"paths"屬性宣告此類對映。
以下是如何為jquery指定"paths"屬性的示例。
{ "compilerOptions": { "baseUrl": ".", // This must be specified if "paths" is. "paths": { "jquery": ["node_modules/jquery/dist/jquery"] // This mapping is relative to "baseUrl" } } }
請注意,相對於"baseUrl"解析"paths"。
當將"baseUrl"設定為"."之外的另一個值,即tsconfig.json的目錄時,必須相應地更改對映。
比如說,你在上面的例子中設定了"baseUrl": "./src",然後jquery應該對映到"../node_modules/jquery/dist/jquery"
使用"paths"還允許更復雜的對映,包括多個後退位置。
考慮一個專案配置,其中只有一些模組在一個位置可用,其餘模組在另一個位置。
構建步驟將它們放在一個地方。
專案佈局可能如下所示:
projectRoot ├── folder1 │ ├── file1.ts (imports 'folder1/file2' and 'folder2/file3') │ └── file2.ts ├── generated │ ├── folder1 │ └── folder2 │ └── file3.ts └── tsconfig.json
相應的tsconfig.json如下所示:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"*": [
"*",
"generated/*"
]
}
}
}
這告訴編譯器任何與模式"*"(即所有值)匹配的模組匯入,以檢視兩個位置:
1) "*"表示同名不變,因此map <moduleName> => <baseUrl>/<moduleName>
2) "generated/*"表示帶有附加字首"generated"的模組名稱,因此map <moduleName> => <baseUrl>/generated/<moduleName>
遵循此邏輯,編譯器將嘗試解析這兩個匯入:
1) import 'folder1/file2'
1. 模式'*'匹配,萬用字元捕獲整個模組名稱
2. 嘗試列表中的第一個替換:'*' -> folder1/file2
3. 替換結果是非相對名稱 - 將其與baseUrl -> projectRoot/folder1/file2.ts結合使用。
4. 檔案已存在。完成。
2) import 'folder2/file3'
1. 模式'*'匹配,萬用字元捕獲整個模組名稱
2. 嘗試列表中的第一個替換:'*' -> folder2/file3
3. 替換結果是非相對名稱 - 將其與baseUrl -> projectRoot/folder2/file3.ts結合使用。
4. 檔案不存在,移動到第二個替換
5. 第二次替換'generated/*' -> generated/folder2/file3
6. 替換結果是非相對名稱 - 將它與baseUrl -> projectRoot/generated/folder2/file3.ts結合使用
7. 檔案已存在。完成。
使用rootDirs的虛擬目錄
有時,編譯時來自多個目錄的專案源都被組合在一起以生成單個輸出目錄。
這可以看作是一組源目錄建立一個"虛擬"目錄。
使用'rootDirs',您可以通知編譯器構成此"虛擬"目錄的根;
因此編譯器可以解析這些"虛擬"目錄中的相關模組匯入,就像在一個目錄中合併在一起一樣。
例如,考慮這個專案結構:
src
└── views
└── view1.ts (imports './template1')
└── view2.ts
generated
└── templates
└── views
└── template1.ts (imports './view2')
src/views中的檔案是某些UI控制元件的使用者程式碼。
生成/模板中的檔案是由模板生成器自動生成的UI模板繫結程式碼,作為構建的一部分。
構建步驟會將/src/views和/generated/templates/views中的檔案複製到輸出中的同一目錄。
在執行時,檢視可以期望其模板存在於其旁邊,因此應使用相對名稱"./template"將其匯入。
要指定與編譯器的此關係,請使用"rootDirs"。
"rootDirs"指定一個根列表,其內容應在執行時合併。
因此,按照我們的示例,tsconfig.json檔案應如下所示:
{
"compilerOptions": {
"rootDirs": [
"src/views",
"generated/templates/views"
]
}
}
每次編譯器在其中一個rootDirs的子資料夾中看到相對模組匯入時,它將嘗試在rootDirs的每個條目中查詢此匯入。
rootDirs的靈活性不僅限於指定邏輯合併的物理源目錄列表。
所提供的陣列可以包括任意數量的ad hoc,任意目錄名,而不管它們是否存在。
這允許編譯器以型別安全的方式捕獲複雜的捆綁和執行時功能,例如條件包含和專案特定的載入器外掛。
考慮一種國際化場景,其中構建工具通過插入特殊路徑令牌(例如#{locale})自動生成特定於語言環境的包,作為相對模組路徑的一部分,例如./#{locale}/messages。
在此假設設定中,該工具列舉支援的語言環境,將抽象的路徑對映到./zh/messages,./de/messages等。
假設每個模組都匯出一個字串陣列。
例如./zh/messages可能包含:
export default [
"您好嗎",
"很高興認識你"
];
通過利用rootDirs,我們可以通知編譯器這個對映,從而允許它安全地解析./#{locale}/messages,即使該目錄永遠不存在。
例如,使用以下tsconfig.json配置:
{
"compilerOptions": {
"rootDirs": [
"src/zh",
"src/de",
"src/#{locale}"
]
}
}
編譯器現在將解析來自'./#{locale}/messages'的匯入訊息,以便從工具中匯入來自'./zh/messages'的訊息,允許以區域設定無關的方式進行開發,而不會影響設計時支援。
未完待續...