前言

笔者最早在vue-cli3(vue 的工具链)中看到的这种前端代码的部署方式,并在生产环境做了部署,但是各种原因并没有发现什么优势。不过这是一个很酷的技术,笔者尝试很多种方式也未能自己实现类似的在 vue 框架下的现代打包方式。

什么是现代打包方式

Deploying ES2015+ Code in Production Today

尽管目前所有的前沿浏览器都能运行 ES2015+ 代码(译注:ES2015 及俗称的 ES6),自然也能够支持我刚刚列举的新特性,,但是为了兼容占有小比例的低版本浏览器用户,大部分的开发者仍然使用 polyfills 将代码编译成 ES5 语法。

这种情况无疑糟透了,在理想的世界里,我们将无需输送不必要的代码!

该文的中文翻译: https://jdc.jd.com/archives/4911

简单的来讲,JavaScript新的版本语法特性、api 等无法和老版本浏览器兼容。但是开发者还想使用新的语法特性,怎么办呢?这个时候就该babeljs出场了。

配合babeljs和各类的polyfill(实现某个 api 的 JS 包,用来补齐 JS 运行环境 api 缺失),前端开发者可以书写任意版本的 JS 语法和 JS 相关 api 而不用考虑浏览器兼容性问题。

然而随着浏览器版本的更新,老版本浏览器市场占比越来越低,而为了兼容那一小撮老版的浏览器,增加各类的polyfill代码包、babeljs转义代码,这也将不再合适。

然而毕竟有老版本浏览器在使用不能放弃他们,所以面向现代模式的 JS 打包方式应运而生。

babel一词的来历

babel 一词来自《圣经·旧约》的记载巴别塔。当时的人们想要修筑直上云霄的巴别塔和上帝同在,被上帝惩罚所有人说不同的语言,最后大家因为语言不通各自离开,巴别塔也没有建成。这里 babeljs 借用这个寓意让不同的 js 语法都能转换成一种。

现代模式的实现方式

这里摘抄 vue-cli3 实现方式:

1
vue-cli-service build --modern

通过 --modern npm 参数构建两种 JS 包,一个现代版的包,面向支持 ES modules 的现代浏览器,另一个旧版的包,面向不支持的旧浏览器。

  • 现代版的包会通过 <script type="module"> 在被支持的浏览器中加载;它们还会使用<link rel="modulepreload"> 进行预加载。
  • 旧版的包会通过 <script nomodule> 加载,并会被支持 ES modules 的浏览器忽略。
  • 一个针对 Safari 10 中 <script nomodule> 的修复会被自动注入。

非常酷的实现方式,这样新旧浏览器分别会走两个包,新版浏览器加载更小的现代版 JS 语法包,老版浏览器则保持不变。 笔者经过打包的项目,新包比老包大概能缩减 100k 左右的大小,vue-cli3 文档指出可以缩减 16%。

尝试 diy 现代打包工具(目前还没成熟的项目)

参考文档

Serve modern code to modern browsers for faster page loads