谈谈babel的preset-env
引言
大家直到babel是现在前端开发的必备工具,如果缺少的babel,很多web项目很可能在浏览器中运行不起来。用好babel不仅对web前端项目的性能优化而且对在平时的新技术积累都大有毗益。
babel配置和核心在于presets和plugins,这两项配置定义了你可以使用哪些es的语法特性。presets的配置有很多,想用可以自行去npm网站,通过babel preset等关键字搜索使用。目前babel官网维护的只有四个presets,分别是
- @babel/preset-env:es语法编译
- @babel/preset-flow:编译js代码静态类型检查器flow
- @babel/preset-react:编译react语法
- @babel/preset-typescript:编译ts语法
本篇文章主要要讲的是@babel/preset-env,其他几个有机会我们再谈。
在谈@babel/preset-env之前,我想我们应该先了解一下JavaScript和EcmaScript的发展历史,以便后续大家能够更好的理解其配置和更新机制。
JavaScript和ECMAScript发展历史
由来
Netscape在1995的时候开发出一种嵌入到浏览器中的语言,一开始叫LiveScript,后来由于推广的需要,将LiveScript重命名为JavaScript,从借着sun公司Java的东风,JavaScript大受欢迎。然而次年8月(1996年8月)微软眼红了,就模仿JavaScript开发了一种相近的语言叫JScript。通过windows强制绑定IE的方式大力推广。此时的Netscape感觉到了危机,决定将JavaScript交给欧洲信息和通信系统标准化协会ECMA(European Computer Manufacturers Association),希望JavaScript成为国际标准,从而可以通过组织的力量限制微软这个不守规则熊孩子。ECMA成立了第39号技术委员会TC39(Technical Committee 39)负责制定和审核这个标准,并于1997年7月组织发布了262号标准文件(ECMA-262)的第一版。ECMA-262规定了浏览器脚本语言的标准,并将这种语言称为 ECMAScript。这个版本就是ECMAScript 1.0 版。当然标准不叫JavaScript的原因,一方面是专利问题,另一方面是避嫌,再有就是要彰显ECMA的功绩了。
历程
ECMAScript标准的发布历史如下:
- 1997年7月,ECMAScript 1.0发布。
- 1998年6月,ECMAScript 2.0版发布。
- 1999年12月,ECMAScript 3.0版发布,成为 JavaScript 的通行标准,得到了广泛支持。
- 2007年10月,ECMAScript 4.0版草案发布,对3.0版做了大幅升级,预计次年8月发布正式版本。草案发布后,由于4.0版的目标过于激进,各方对于是否通过这个标准,发生了严重分歧。以 Yahoo、Microsoft、Google 为首的大公司,反对 JavaScript 的大幅升级,主张小幅改动;以 JavaScript 创造者 Brendan Eich 为首的 Mozilla 公司,则坚持当前的草案。
- 2008年7月,由于对于下一个版本应该包括哪些功能,各方分歧太大,争论过于激进,ECMA 开会决定,中止 ECMAScript 4.0 的开发(即废除了这个版本),将其中涉及现有功能改善的一小部分,发布为 ECMAScript 3.1,而将其他激进的设想扩大范围,放入以后的版本,由于会议的气氛,该版本的项目代号起名为 Harmony(和谐)。会后不久,ECMAScript 3.1 就改名为 ECMAScript 5。
- 2009年12月,ECMAScript 5.0版 正式发布。Harmony 项目则一分为二,一些较为可行的设想定名为 JavaScript.next 继续开发,后来演变成 ECMAScript 6;一些不是很成熟的设想,则被视为 JavaScript.next.next,在更远的将来再考虑推出。TC39 的总体考虑是,ECMAScript 5 与 ECMAScript 3 基本保持兼容,较大的语法修正和新功能加入,将由 JavaScript.next 完成。当时,JavaScript.next 指的是ECMAScript 6。第六版发布以后,将指 ECMAScript 7。TC39 预计,ECMAScript 5 会在2013年的年中成为 JavaScript 开发的主流标准,并在此后五年中一直保持这个位置。
- 2011年6月,ECMAScript 5.1版发布,并且成为 ISO 国际标准(ISO/IEC 16262:2011)。到了2012年底,所有主要浏览器都支持 ECMAScript 5.1版的全部功能。
- 2013年3月,ECMAScript 6 草案冻结,不再添加新功能。新的功能设想将被放到 ECMAScript 7。
- 2013年12月,ECMAScript 6 草案发布。然后是12个月的讨论期,听取各方反馈。
- 2015年6月,ECMAScript 6 正式发布,并且更名为“ECMAScript 2015”。这是因为 TC39 委员会计划,以后每年发布一个 ECMAScript 的版本,下一个版本在2016年发布,称为“ECMAScript 2016”,2017年发布“ECMAScript 2017”,以此类推。
可以看到,前面几个版本7-8年才发布一次,发版频率还是比较平缓的,但是到了es5以后新版本的发布时间就大幅缩减了,到了es6以后tc39已经明确每年做一个版本的迭代。
在不考虑IE的情况下(因为IE109以前基本没有遵循这个规范),15年以前,浏览器厂商还有几年的时间去迭代新的标准,15年以后就基本每年都要却迭代一个新标准了,所以浏览器厂商对于标准的实现肯定是远远滞后的。于是,你想用最新的语法的话,就不得不选用babel去对最新的语法编译转换成浏览器支持的语法,确保自己的应用代码不会在浏览器中无法运行。
ECMAScript标准制定过程
在某些新特性纳入ECMAScript标准之前,会经历一个提案的过程,TC39将提案分为5各阶段:
- Stage 0 - 稻草人阶段,草案阶段。
- Stage 1 - 提议: 探讨阶段。
- Stage 2 - 草稿: 可以做规范的初始化了
- Stage 3 - 候选: 完整的规范和初始浏览器实现。
- Stage 4 - 结束: 将被添加到下一个年度版本中。
一般在进入stage3之前的特性都是十分不稳定的,非常不推荐大家去使用这种语法特性。进入stage4以后,这个规范会在下一个年度版本中发布。因此@babel/preset-env默认会支持stage4的特性转换(当然是针对@babel/preset-env当前版本发布年份的stage4提案)。
@babel/preset-env的作用
@babel/preset-env在官网介绍是一款自动管理浏览器版本和babel语法转换插件映射的一款工具。其中浏览器版本管理默认使用的是browserslist,可以通过browserslist的相关配置去指定需要兼容的浏览器版本列表。 @babel/preset-env会在编译的时候自动匹配需要使用哪些plugins去转换的你代码,默认会纳入该 @babel/preset-env版本发布前的ECMAScript的stage4提案内容。
关于babel在性能优化中的作用
既然 @babel/preset-env涉及到项目的编译,那么对编译出来的生产包的大小有着决定性的作用。实践证明,babel兼容ie11与babel兼容chrome60,打包出来的包大小有着1/6大小差异(占兼容ie11的包大小)。所以合理的browserslist配置对于项目的性能有很大的帮助。具体browserlist配置请参考browserslist官网,这里不再做赘述。
关于async和await调试
可能很多人在用babel编译后,发现调试async和await变得很困难,chrome开发者工具甚至不能在await所在代码行中增加断点。这里有一个小技巧,可以解决这个问题:
- 在.babelrc文件中增加如下retainLines的配置,使其支持generator的行数映射还原
{
// ...
"env": {
"development": {
"retainLines": true
}
}
}
- 设置webpack的devtool为“cheap-module-source-map”和“cheap-module-eval-source-map”即可。
具体sourcemap如何实现的尚未深入研究。今日@babel/preset-env就讲到这里,如果大家还有什么疑问,欢迎在评论中提出,一起交流交流使用心得。