生产环境部署es6代码

1次阅读

共计 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 代码的性能对比,我也用一个线上项目进行了实验。实验方式如下

  1. 利用 performance API 在打包后的 app.js 文件开头记下时间戳,在 js 文件末尾减去开始的时间,得到一个时间,众所周知,打包之后的 app.js 是一个立即执行函数,所以这个时间包含了 app.js 文件中 部分代码 的运行时间
  2. 利用 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…
正文完
 0