【TypeScript系列】模块解析

模块解析

这节假设你已经了解了模块的一些基本知识 请阅读模块文档了解更多信息。

_模块解析_是指编译器在查找导入模块内容时所遵循的流程。 假设有一个导入语句import { a } from "moduleA"; 为了去检查任何对a的使用,编译器需要准确的知道它表示什么,并且需要检查它的定义moduleA

这时候,编译器会有个疑问“moduleA的结构是怎样的?” 这听上去很简单,但moduleA可能在你写的某个.ts/.tsx文件里或者在你的代码所依赖的.d.ts里。

首先,编译器会尝试定位表示导入模块的文件。 编译器会遵循以下二种策略之一:ClassicNode。 这些策略会告诉编译器到_哪里_去查找moduleA

如果上面的解析失败了并且模块名是非相对的(且是在"moduleA"的情况下),编译器会尝试定位一个外部模块声明。 我们接下来会讲到非相对导入。

最后,如果编译器还是不能解析这个模块,它会记录一个错误。 在这种情况下,错误可能为error TS2307: Cannot find module 'moduleA'.

相对 vs. 非相对模块导入

根据模块引用是相对的还是非相对的,模块导入会以不同的方式解析。

_相对导入_是以/./../开头的。 下面是一些例子:

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

所有其它形式的导入被当作_非相对_的。 下面是一些例子:

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

相对导入在解析时是相对于导入它的文件,并且_不能_解析为一个外部模块声明。 你应该为你自己写的模块使用相对导入,这样能确保它们在运行时的相对位置。

非相对模块的导入可以相对于baseUrl或通过下文会讲到的路径映射来进行解析。 它们还可以被解析成外部模块声明。 使用非相对路径来导入你的外部依赖。

模块解析策略

共有两种可用的模块解析策略:NodeClassic。 你可以使用--moduleResolution标记来指定使用哪种模块解析策略。 若未指定,那么在使用了--module AMD | System | ES2015时的默认值为Classic,其它情况时则为Node

Classic

这种策略在以前是TypeScript默认的解析策略。 现在,它存在的理由主要是为了向后兼容。

相对导入的模块是相对于导入它的文件进行解析的。 因此/root/src/folder/A.ts文件里的import { b } from "./moduleB"会使用下面的查找流程:

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

对于非相对模块的导入,编译器则会从包含导入文件的目录开始依次向上级目录遍历,尝试定位匹配的声明文件。

比如:

有一个对moduleB的非相对导入import { b } from "moduleB",它是在/root/src/folder/A.ts文件里,会以如下的方式来定位"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

这个解析策略试图在运行时模仿Node.js模块解析机制。 完整的Node.js解析算法可以在Node.js module documentation找到。

Node.js如何解析模块

为了理解TypeScript编译依照的解析步骤,先弄明白Node.js模块是非常重要的。 通常,在Node.js里导入是通过require函数调用进行的。 Node.js会根据require的是相对路径还是非相对路径做出不同的行为。

相对路径很简单。 例如,假设有一个文件路径为/root/src/moduleA.js,包含了一个导入var x = require("./moduleB"); Node.js以下面的顺序解析这个导入:

  1. 检查/root/src/moduleB.js文件是否存在。
  2. 检查/root/src/moduleB目录是否包含一个package.json文件,且package.json文件指定了一个"main"模块。 在我们的例子里,如果Node.js发现文件/root/src/moduleB/package.json包含了{ "main": "lib/mainModule.js" },那么Node.js会引用/root/src/moduleB/lib/mainModule.js
  3. 检查/root/src/moduleB目录是否包含一个index.js文件。 这个文件会被隐式地当作那个文件夹下的"main"模块。

你可以阅读Node.js文档了解更多详细信息:file modulesfold

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值