1. 程式人生 > >TypeScript基礎入門之模組解析(二)

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'的訊息,允許以區域設定無關的方式進行開發,而不會影響設計時支援。

未完待續...