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必须也指定为这个值,否则会报错。
此时会要求引入文件显式的带上文件后缀名,否则会报错。
文件具体的解析策略则和node策略保持一致。
-
Bundler
一个比较新的策略,主要是为了妥协社区标准。因为node16/nodenext规定非常严格,很多三方库并没有按该标 准去区分模块导出,导致这个标准几乎没人用。bundler的出现就是为了使用package.json的exports字段同时,同时不用写文件扩展名。
关于bundler、node16/nodenext和node策略的故事,推荐阅读 moduleResolution 总结 写的非常详细。