tsconfig中target、module与moduleResolution字段简析

803 阅读5分钟

target-目标ES版本

ES版本号

ECMAScript和JavaScript的故事由来已久。1996年网景将JavaScript提交给ECMA International(欧洲计算机制造商协会)进行标准化,产生的结果就是ECMAScript。我们可以理解ECMAScript是一种标准,而JavaScript则是在这个**标准下的实现。**当然也有别的实现同样遵循ECMAScript标准,例如ActionScript(Adobe Flash的脚本语言)

目前es标准由TC39委员会负责制定(官网:tc39.es/)我们称一般有两种方式…

  • es[version],version是ECMAScript的第几版本标准

  • es[year],year对应该标准发布的年份

不过一般来说,我们只对es5和es6按版本号称呼,后来的基本都是按照年号来称呼。

es早期版本更迭是比较慢的,我们熟知的es5标准发布2009年,es6标准发布于2015年。而正式从2015年开始,每一年会发发布一个新的版本。对应的版本的是这个样子的

es5-es2009

es6-es2015

es7-es2016

es8-es2017

...

可以看到从es6开始版本发布的更快了,每个新版本更新也变得更小了。例如es2016,实际上只有两个新的提议:数组的includes()方法,和使用**作为幂运算符。

还有两个比较特殊的

  • esnext,代指下一年发布的es版本。例如在今年(2023年)指定版本为esnext的话,就会包括到还没有发布的es2024版本中的新feature。

  • es harmony,这并不是一个支持的配置项,只是一个俗称。这个称呼比较老了,不是非常常见。用来代指对于es5的所有的扩展版本,有点类似于对于最新版es的指代,偶尔也会被用来指代es6

使用新提案

ES每一个新提案都要经过5个阶段

  • 稻草人阶段,开始提议前的简单草案

  • 成熟阶段

只有经过这几个阶段之后,一个提案才会被发布出来,对于每个阶段具体做了什么可以参考官网,同时也可以在tc39的官网查看每个提案到了什么阶段。

而我们需要使用这些提案时(也就是target指定为对应版本时),首先需要考虑的就是环境是否支持。

对于浏览器环境,我们可以去caniuse.com/上查阅一下,看看是浏览…

而对于node环境,则可以去node.green/上查阅一下对应的支持。

module-目标模块标准

module指定了生成代码使用的模块标准。其中支持的 CJS(commonjs)、AMD、UMD和ESM(es module)这些js模块标准已经是老生常谈了,就不多提。主要介绍一下其余比较特殊的module定义

  • es2015

这下我们知道了,es2015也就是es6,实际上就是我们常用的ESM模块标准

  • es2020

    es2020添加了对于动态import的支持,也就是import()用法,同时也添加了对于import.meta的支持。目标代码中就会带上新标准的代码

  • es2022

    和2020类似,主要处理es2022支持的top-level-await

  • esnext

    代指未发布的es2024,目前来说不会有什么影响模块化的提案,所以效果同es2022

  • node16/nodenext

    这个比较特殊,用来适配node对es module模块的原生支持的,严格遵循node的导出导入逻辑。node从v12开始,原生支持ESM和CommonJs两中模块标准。在这个module模式下,输出允许使用多种模块标准。对应到每个输出文件具体要使用什么模块标准,由两种方式决定

    ts会根据对应的标准对模块引入进行检查,不合标准的会报错

    同时,每个node的具体版本对于ESM的支持略有差别

    所以在这个模式下,tsc会读取package.json中的node字段,根据具体的node版本来决定具体文件的输出。

    关于node对于ESM的支持,可以参考node文档nodejs.org/api/esm.htm…

moduleResolution-模块解析策略

moduleResolution这个字段主要是决定根据一个路径去查找到对应的模块。

  • classic

经典策略,会从子文件夹开始递归的向外查找。这个模式更多是用来向后兼容,官方不推荐使用

  • node

node解析策略,会按照node解析引入文件的策略进行解析

  • node16/nodenext

    用于适配node策略下对于ESM和CommonJs同时支持的场景。当module指定为node16/nodenext时,moduleResolution必须也指定为这个值,否则会报错。

    此时会要求引入文件显式的带上文件后缀名,否则会报错。

image

文件具体的解析策略则和node策略保持一致。

  • Bundler

    一个比较新的策略,主要是为了妥协社区标准。因为node16/nodenext规定非常严格,很多三方库并没有按该标 准去区分模块导出,导致这个标准几乎没人用。bundler的出现就是为了使用package.json的exports字段同时,同时不用写文件扩展名。

    关于bundler、node16/nodenext和node策略的故事,推荐阅读 moduleResolution 总结 写的非常详细。