轉發 TypeScript基礎入門之模塊解析(二)node
使用baseUrl是使用AMD模塊加載器的應用程序中的常見作法,其中模塊在運行時"deployed"到單個文件夾。
這些模塊的源代碼能夠存在於不一樣的目錄中,但構建腳本會將它們放在一塊兒。jquery
設置baseUrl通知編譯器在哪裏能夠找到模塊。
假定全部具備非相對名稱的模塊導入都相對於baseUrljson
baseUrl的值肯定爲:數組
1) baseUrl命令行參數的值(若是給定的路徑是相對的,則根據當前目錄計算)
2) 'tsconfig.json'中baseUrl屬性的值(若是給定的路徑是相對的,則根據'tsconfig.json'的位置計算)安全
請注意,設置baseUrl不會影響相對模塊導入,由於它們始終相對於導入文件進行解析。
您能夠在RequireJS和SystemJS文檔中找到有關baseUrl的更多文檔。app
有時模塊不直接位於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"ui
使用"paths"還容許更復雜的映射,包括多個後退位置。
考慮一個項目配置,其中只有一些模塊在一個位置可用,其他模塊在另外一個位置。
構建步驟將它們放在一個地方。
項目佈局可能以下所示:spa
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',您能夠通知編譯器構成此"虛擬"目錄的根;
所以編譯器能夠解析這些"虛擬"目錄中的相關模塊導入,就像在一個目錄中合併在一塊兒同樣。
例如,考慮這個項目結構:
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'的消息,容許以區域設置無關的方式進行開發,而不會影響設計時支持。
未完待續...