在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 模塊解析
初始化項(xiàng)目結(jié)構(gòu)
聯(lián)合類型
介紹
介紹
介紹
編譯選項(xiàng)
TypeScript 1.6
介紹
介紹
發(fā)展路線圖
介紹
在MSBuild里使用編譯選項(xiàng)
可迭代性
TypeScript 1.3
介紹
介紹
TypeScript 1.1
變量聲明
即將到來(lái)的Angular 2框架是使用TypeScript開(kāi)發(fā)的。 因此Angular和TypeScript一起使用非常簡(jiǎn)單方便
tsconfig.json
介紹
介紹
介紹
在MSBuild里使用編譯選項(xiàng)
使用TypeScript的每日構(gòu)建版本
新建工程
枚舉
三斜線指令
結(jié)合ASP.NET v5使用TypeScript
TypeScript里的this
介紹
TypeScript 1.4
編碼規(guī)范
介紹
模塊解析
ASP.NET 4
架構(gòu)概述
介紹
介紹
ASP.NET Core
TypeScript 1.8
介紹
介紹
創(chuàng)建簡(jiǎn)單工程
TypeScript 1.7
TypeScript 1.5
NPM包的類型
支持TypeScript的編輯器

模塊解析

這節(jié)假設(shè)你已經(jīng)了解了模塊的一些基本知識(shí) 請(qǐng)閱讀模塊文檔了解更多信息。

模塊解析就是指編譯器所要依據(jù)的一個(gè)流程,用它來(lái)找出某個(gè)導(dǎo)入操作所引用的具體值。 假設(shè)有一個(gè)導(dǎo)入語(yǔ)句import { a } from "moduleA"; 為了去檢查任何對(duì)a的使用,編譯器需要準(zhǔn)確的知道它表示什么,并且會(huì)需要檢查它的定義moduleA

這時(shí)候,編譯器會(huì)想知道“moduleA的shape是怎樣的?” 這聽(tīng)上去很簡(jiǎn)單,moduleA可能在你寫(xiě)的某個(gè).ts/.tsx文件里或者在你的代碼所依賴的.d.ts里。

首先,編譯器會(huì)嘗試定位表示導(dǎo)入模塊的文件。 編譯會(huì)遵循下列二種策略之一:ClassicNode。 這些策略會(huì)告訴編譯器到哪里去查找moduleA。

如果它們失敗了并且如果模塊名是非相對(duì)的(且是在"moduleA"的情況下),編譯器會(huì)嘗試定位一個(gè)外部模塊聲明。 我們接下來(lái)會(huì)講到非相對(duì)導(dǎo)入。

最后,如果編譯器還是不能解析這個(gè)模塊,它會(huì)記錄一個(gè)錯(cuò)誤。 在這種情況下,錯(cuò)誤可能為error TS2307: Cannot find module 'moduleA'.

相對(duì) vs. 非相對(duì)模塊導(dǎo)入

根據(jù)模塊引用是相對(duì)的還是非相對(duì)的,模塊導(dǎo)入會(huì)以不同的方式解析。

相對(duì)導(dǎo)入是以/,./../開(kāi)頭的。 下面是一些例子:

  • import Entry from "./components/Entry";
  • import { DefaultHeaders } from "../constants/http";
  • import "/mod";

所有其它形式的導(dǎo)入被當(dāng)作非相對(duì)的。 下面是一些例子:

  • import * as $ from "jQuery";
  • import { Component } from "angular2/core";

相對(duì)導(dǎo)入解析時(shí)是相對(duì)于導(dǎo)入它的文件來(lái)的,并且不能解析為一個(gè)外部模塊聲明。 你應(yīng)該為你自己寫(xiě)的模塊使用相對(duì)導(dǎo)入,這樣能確保它們?cè)谶\(yùn)行時(shí)的相對(duì)位置。

模塊解析策略

共有兩種可用的模塊解析策略:NodeClassic。 你可以使用--moduleResolution標(biāo)記為指定使用哪個(gè)。 默認(rèn)值為Node。

Classic

這種策略以前是TypeScript默認(rèn)的解析策略。 現(xiàn)在,它存在的理由主要是為了向后兼容。

相對(duì)導(dǎo)入的模塊是相對(duì)于導(dǎo)入它的文件進(jìn)行解析的。 因此/root/src/folder/A.ts文件里的import { b } from "./moduleB"會(huì)使用下面的查找流程:

  1. /root/src/folder/moduleB.ts
  2. /root/src/folder/moduleB.d.ts

對(duì)了非相對(duì)模塊的導(dǎo)入,編譯器則會(huì)從包含導(dǎo)入文件的目錄開(kāi)始依次向上級(jí)目錄遍歷,嘗試定位匹配的聲明文件。

比如:

有一個(gè)對(duì)moduleB的非相對(duì)導(dǎo)入import { b } from "moduleB",它是在/root/src/folder/A.ts文件里,會(huì)以如下的方式來(lái)定位"moduleB"

  1. /root/src/folder/moduleB.ts
  2. /root/src/folder/moduleB.d.ts
  3. /root/src/moduleB.ts
  4. /root/src/moduleB.d.ts
  5. /root/moduleB.ts
  6. /root/moduleB.d.ts
  7. /moduleB.ts
  8. /moduleB.d.ts

Node

這個(gè)解析策略試圖在運(yùn)行時(shí)模仿Node.js模塊解析機(jī)制。 完整的Node.js解析算法可以在Node.js module documentation找到。

Node.js如何解析模塊

為了理解TypeScript編譯依照的解析步驟,先弄明白Node.js模塊是非常重要的。 通常,在Node.js里導(dǎo)入是通過(guò)require函數(shù)調(diào)用進(jìn)行的。 Node.js會(huì)根據(jù)require的是相對(duì)路徑還是非相對(duì)路徑做出不同的行為。

相對(duì)路徑很簡(jiǎn)單。 例如,假設(shè)有一個(gè)文件路徑為/root/src/moduleA.js,包含了一個(gè)導(dǎo)入var x = require("./moduleB"); Node.js以下面的順序解析這個(gè)導(dǎo)入:

  1. /root/src/moduleB.js視為文件,檢查是否存在。

  2. /root/src/moduleB視為目錄,檢查是否它包含package.json文件并且其指定了一個(gè)"main"模塊。 在我們的例子里,如果Node.js發(fā)現(xiàn)文件/root/src/moduleB/package.json包含了{ "main": "lib/mainModule.js" },那么Node.js會(huì)引用/root/src/moduleB/lib/mainModule.js。

  3. /root/src/moduleB視為目錄,檢查它是否包含index.js文件。 這個(gè)文件會(huì)被隱式地當(dāng)作那個(gè)文件夾下的"main"模塊。

你可以閱讀Node.js文檔了解更多詳細(xì)信息:file modulesfolder modules。

但是,非相對(duì)模塊名的解析是個(gè)完全不同的過(guò)程。 Node會(huì)在一個(gè)特殊的文件夾node_modules里查找你的模塊。 node_modules可能與當(dāng)前文件在同一級(jí)目錄下,或者在上層目錄里。 Node會(huì)向上級(jí)目錄遍歷,查找每個(gè)node_modules直到它找到要加載的模塊。

還是用上面例子,但假設(shè)/root/src/moduleA.js里使用的是非相對(duì)路徑導(dǎo)入var x = require("moduleB");。 Node則會(huì)以下面的順序去解析moduleB,直到有一個(gè)匹配上。

  1. /root/src/node_modules/moduleB.js
  2. /root/src/node_modules/moduleB/package.json (如果指定了"main"屬性)
  3. /root/src/node_modules/moduleB/index.js

  4. /root/node_modules/moduleB.js
  5. /root/node_modules/moduleB/package.json (如果指定了"main"屬性)
  6. /root/node_modules/moduleB/index.js

  7. /node_modules/moduleB.js
  8. /node_modules/moduleB/package.json (如果指定了"main"屬性)
  9. /node_modules/moduleB/index.js

注意Node.js在步驟(4)和(7)會(huì)向上跳一級(jí)目錄。

你可以閱讀Node.js文檔了解更多詳細(xì)信息:loading modules from node_modules

TypeScript如何解析模塊

TypeScript是模仿Node.js運(yùn)行時(shí)的解析策略來(lái)在編譯階段定位模塊定義文件。 因此,TypeScript在Node解析邏輯基礎(chǔ)上增加了TypeScript源文件的擴(kuò)展名(.ts,.tsx.d.ts)。 同時(shí),TypeScript在package.json里使用字段"typings"來(lái)表示類似"main"的意義 - 編譯器會(huì)使用它來(lái)找到要使用的"main"定義文件。

比如,有一個(gè)導(dǎo)入語(yǔ)句import { b } from "./moduleB"/root/src/moduleA.ts里,會(huì)以下面的流程來(lái)定位"./moduleB"

  1. /root/src/moduleB.ts
  2. /root/src/moduleB.tsx
  3. /root/src/moduleB.d.ts
  4. /root/src/moduleB/package.json (如果指定了"typings"屬性)
  5. /root/src/moduleB/index.ts
  6. /root/src/moduleB/index.tsx
  7. /root/src/moduleB/index.d.ts

回想一下Node.js先查找moduleB.js文件,然后是合適的package.json,再之后是index.js

類似地,非相對(duì)的導(dǎo)入會(huì)遵循Node.js的解析邏輯,首先查找文件,然后是合適的文件夾。 因此/src/moduleA.ts文件里的import { b } from "moduleB"會(huì)以下面的查找順序解析:

  1. /root/src/node_modules/moduleB.ts
  2. /root/src/node_modules/moduleB.tsx
  3. /root/src/node_modules/moduleB.d.ts
  4. /root/src/node_modules/moduleB/package.json (如果指定了"typings"屬性)
  5. /root/src/node_modules/moduleB/index.ts
  6. /root/src/node_modules/moduleB/index.tsx
  7. /root/src/node_modules/moduleB/index.d.ts

  8. /root/node_modules/moduleB.ts
  9. /root/node_modules/moduleB.tsx
  10. /root/node_modules/moduleB.d.ts
  11. /root/node_modules/moduleB/package.json (如果指定了"typings"屬性)
  12. /root/node_modules/moduleB/index.ts
  13. /root/node_modules/moduleB/index.tsx
  14. /root/node_modules/moduleB/index.d.ts

  15. /node_modules/moduleB.ts
  16. /node_modules/moduleB.tsx
  17. /node_modules/moduleB.d.ts
  18. /node_modules/moduleB/package.json (如果指定了"typings"屬性)
  19. /node_modules/moduleB/index.ts
  20. /node_modules/moduleB/index.tsx
  21. /node_modules/moduleB/index.d.ts

不要被這里步驟的數(shù)量嚇到 - TypeScript只是在步驟(8)和(15)向上跳了兩次目錄。 這并不比Node.js里的流程復(fù)雜。

使用--noResolve

正常來(lái)講編譯器會(huì)在開(kāi)始編譯之前解析模塊導(dǎo)入。 每當(dāng)它成功地解析了對(duì)一個(gè)文件import,這個(gè)文件被會(huì)加到一個(gè)文件列表里,以供編譯器稍后處理。

--noResolve編譯選項(xiàng)告訴編譯器不要添加任何不是在命令行上傳入的文件到編譯列表。 編譯器仍然會(huì)嘗試解析模塊,但是只要沒(méi)有指定這個(gè)文件,那么它就不會(huì)被包含在內(nèi)。

比如

app.ts

import * as A from "moduleA" // OK, moduleA passed on the command-line
import * as B from "moduleB" // Error TS2307: Cannot find module 'moduleB'.
tsc app.ts moduleA.ts --noResolve

使用--noResolve編譯app.ts

  • 可能正確找到moduleA,因?yàn)樗诿钚猩现付恕?/li>
  • 找不到moduleB,因?yàn)闆](méi)有在命令行上傳遞。

常見(jiàn)問(wèn)題

為什么在exclude列表里的模塊還會(huì)被編譯器使用

tsconfig.json將文件夾轉(zhuǎn)變一個(gè)“工程” 如果不指定任何“exclude”“files”,文件夾里的所有文件包括tsconfig.json和所有的子目錄都會(huì)在編譯列表里。 如果你想利用“exclude”排除某些文件,甚至你想指定所有要編譯的文件列表,請(qǐng)使用“files”。

有些是被tsconfig.json自動(dòng)加入的。 它不會(huì)涉及到上面討論的模塊解析。 如果編譯器識(shí)別出一個(gè)文件是模塊導(dǎo)入目標(biāo),它就會(huì)加到編譯列表里,不管它是否被排除了。

因此,要從編譯列表中排除一個(gè)文件,你需要在排除它的同時(shí),還要排除所有對(duì)它進(jìn)行import或使用了/// <reference path="..." />指令的文件。

上一篇:可迭代性下一篇:ASP.NET Core