共计 2301 个字符,预计需要花费 6 分钟才能阅读完成。
时间流转,来到了 9102 年的末尾,距离 es6 正式发布已经过去了 4 年半。在前端发展的时间长河中,我们送别了 YUI,ie(也许),jQuery,现在,是时候送别 es5 了。
收益在哪
程序员在进行技术决策的时候,通常的目的是为了 kpi, 升值加薪 , 这个技术很流行,不,当然是为了对业务产生价值。
不难发现,直接部署 es6 代码可以带来的好处包括:
- 代码体积减小
- 性能提升
- 缩短构建时间
代码体积减小
首先,es6 带来了新的语法和特性,这可以让代码更简洁,使得代码量减少。其次,babel 转译之后,会产生一些helper
,引入一些polyfill
,而且有一些语法特性无法在运行时进行处理,必须在转译过程中修改源代码,这也会导致代码量增加。当然,部署 es6 代码也需要 babel 转译一部分更新的语法,并不是说完全不使用 babel。
一个 Google 工程师的试验结果,es6 代码的 bundle size 比 es5 代码减少了50%。而我自己的实践的结果没有这么夸张,是25% 左右。
version | bundle size | Gzipped |
---|---|---|
es5 | 221kb | 39kb |
es6 | 170kb | 29kb |
之所以我和他的测试结果差异较大,是因为最终的结果跟每个人的代码风格和代码内容有很大的关系。我用来进行测试的代码是一个线上项目的代码,我个人的代码风格是大量使用 es6/7/ 8 语法,不过项目本身大量是在写业务逻辑,并且项目使用了 Vue,其实很多 js 代码是模板编译之后生成的渲染函数。
所以,大概的结论是 es6 的代码会比 es5 的代码体积减少15% ~ 50%,具体能减少多少,取决于代码风格以及代码内容。代码风格越现代,代码中 ” 生成的代码 ” 越少,收益越高。
性能提升
es6 代码相对于 es5 代码,性能更高的原因我认为有 2 个
- 代码量减少带来的解析时间减少,这个正比于代码体积的减少
- 运行性能的提高
对于第一点,浏览器解析代码时间的减少应该占比较小,通过 chrome 的 Performance
面板可以看到,解析一个 200kb 的 js 文件 Compile Script 耗时为10ms(测试机器为台式机,i7/16G)。
对于第二点,运行时性能。在 es6 刚刚发布的时候,很多新特性的性能是比较低的,因为 js 引擎没有足够的时间去进行优化,相比较而言,es5 以及更老的代码经过了浏览器的长时间优化,在 es6 刚出来的时候,很对人也对 es6 的性能有很大的担忧。
Github 上有一个仓库,专门对 es6 和 es5 进行了性能对比。
从对比结果可以看出来,在 chrome 72 版本上,es6 代码的性能优于 babel 转译成的 es5 代码,和手写的 es5 代码比起来各有千秋,基本算是 55 开。
而且,浏览器对于 es6 的性能优化是持续性的,最近 V8 就会因为 React hooks
而改进数组解构的性能。
针对运行时的 es6 代码和 es5 代码的性能对比,我也用一个线上项目进行了实验。实验方式如下
- 利用
performance API
在打包后的 app.js 文件开头记下时间戳,在 js 文件末尾减去开始的时间,得到一个时间,众所周知,打包之后的 app.js 是一个立即执行函数,所以这个时间包含了 app.js 文件中 部分代码 的运行时间 - 利用 chrome 的
Performance
面板,可以直接得到一段 js 的执行时间Evaluate Script
实验结果如下(20 次的平均值)
version | 记录的运行时间 | Performance 面板的 Evaluate Script |
---|---|---|
es5 | 258.88ms | 295.29ms |
es6 | 206.28ms | 241.59ms |
测试条件下,es6 的代码取得了 20% 左右 的运行性能提升
风险在哪儿
js 的运行环境非常复杂,桌面端、移动端、各种小程序、各种 webview、node.js,能否部署 es6 代码只能依靠自己判断。
就我个人的经验而言,大部分的中后台项目都具备直接部署 es6 代码的条件,而且我们在具体的实施中肯定会有降级方案,让不支持 es6 的情况下运行 es5 的代码。
如何实施
Vue 用户可以通过 Vue cli 的 --modern
直接开启现代模式
非 Vue 使用者,可以通过这篇文章提到的方案来进行。大概就是利用 script
标签的 type=module
作为浏览器是否全面支持 es6 的检测,并通过 type=nomodule
来进行降级处理。
// 不支持 module 的浏览器,下载但不会执行
<script type="module" src="es6.js"></script>
// 支持 module 的浏览器,不会下载
<script nomodule src="es5.js"></script>
一个需要注意的点是 safari 10 不支持 nomodule,所以需要针对它解决重复下载并执行的问题。(ps: safari 浏览器是新时代的毒瘤)
虽然,一个降级的方案可以保证我们的代码可以在只支持 es5 的浏览器上也可以执行,但是同时这些老的浏览器会下载 2 份代码,带来的损失非常大,因为老设备通常也意味着低性能和低网速,它们更不能承受性能损失。所以我认为,如果你的业务需要兼容 es5 的用户达到了 20% 以上,我就不赞同采用这个方案。
如果可以确定完全不需要兼容 es5 的用户,可以直接修改 browserlist
到全面支持 es6 的浏览器版本,并且不用考虑降级方案,此时还会带来构建速度提升这一额外的好处。
browserslist 示例
Chrome >= 60
Safari >= 10.1
iOS >= 10.3
Firefox >= 54
Edge >= 15
结语
时间带走一切,es5 也不例外。
参考
- deploying-es2015-code-in-production-today
- https://myst729.github.io/pos…