我们可以编写“未来派”的 JavaScript。“Stage 0”指的是 JavaScript 语言的一些想法,这些想法目前仍处于提案阶段。尽管如此,有人可能会将该想法转换为Babel 插件,并且它可以编译成可以交付到任何浏览器的代码。对于其中一些幸运的提案,Stage 0 会变成 1、2、3,最终成为语言的正式组成部分。
曾经有一段时间,即使是 ES6 的基本特性也相当实验性。您永远不会将箭头函数交付到生产环境中——您会将其编译为 ES5 并交付它。但 ES6(又名 ES2015,四年前!)不再是实验性的了。它的特性不是提案、草案或候选方案。它们是语言的完成部分,并得到广泛的支持。
浏览器支持的主要障碍是 IE <= 11 和 Safari <= 9。您完全有可能不支持这些浏览器。在这种情况下,您可以自由地将 ES6 特性交付到生产环境中,并且您可能应该这样做,因为与将其编译为 ES5 相比,您的代码将更小、更高效。Philip 进行了一些测试,并且他的结果表明,通过采用新特性,文件大小和解析/评估时间可以减少一半甚至更多。但是,如果您确实需要支持缺少支持的浏览器,则需要编译为 ES5,但这并不意味着您需要向所有浏览器交付 ES5。这就是“差异化服务”的意义所在。
您如何实现它?一种方法,非常巧妙,是我第一次看到 Philip Walton撰写关于此方法的文章
<!-- Browsers with ES module support load this file. -->
<script type="module" src="main.mjs"></script>
<!-- Older browsers load this file (and module-supporting -->
<!-- browsers know *not* to load this file). -->
<script nomodule src="main.es5.js"></script>
不要让 .mjs
这些内容让您困惑;它只是一个虚构的文件扩展名,表示“这是一个支持 import
ES6 模块的 JavaScript 文件”,并且它完全是可选的。我可能甚至不会使用它。
不过,这个概念很棒。我们不必编写花哨的 JavaScript 特性测试,然后自己启动对正确 bundle 的网络请求。我们可以在 HTML 级别直接进行拆分。我甚至看到一些小型库使用这种方法来限定自身范围,专门针对现代浏览器。
John Stewart 最近对它进行了一些测试,以查看它是否按我们预期的那样工作,如果是,则它是否工作良好。首先,他介绍了如何实际创建两个 bundle,这需要一些 webpack 配置。然后他测试了它是否真的有效。
好消息是,大多数浏览器——特别是较新的浏览器——在差异化服务方面表现得非常好。但有一些浏览器没有。Safari 10(2016)是一个特别严重的违规者,因为它会下载并执行两个版本。Firefox 59(2018)和 IE 11 会下载两者(但会执行正确的版本),而 Edge 18 则会以某种方式下载两个版本,然后再次下载模块版本。所有这些浏览器都很快就会消失,但不能忽视。仍然值得这样做吗?可能。我很有兴趣研究对抗这些缺陷的替代技术。
我根据用户代理提供正确的包
此处描述了不会出现缺陷的替代方案
https://medium.com/@WebReflection/a-universal-bundle-loader-6d7f3e628f93
简而言之
type=module
(请始终记住不需要 .mjs)在延迟脚本之前加载示例
ubl.js(通用 Bundle 加载器)将包含几行代码
就是这样
这可以确保每个浏览器都能以最佳方式工作,从旧到新。
为了获得最佳结果,捆绑的代码应针对 ES 2017、2015 和 5,但它也可以简单地针对
type=module
使用 2015,针对nomodule
使用 5。我最近偶然发现了https://github.com/Polymer/prpl-server/blob/master/README.md#differential-serving,它可以通过使用用户代理标头检测浏览器功能来向不同的浏览器提供应用程序的不同版本。您可以按照 Polymer 入门套件示例https://github.com/Polymer/polymer-starter-kit进行测试。
有一个 JavaScript 解决方案可以帮助解决 Safari 10.1 问题。https://gist.github.com/samthor/64b114e4a4f539915a95b91ffd340acc
Safari 10.1 不是唯一一个。这里有一个基于特性检测而不是 UA 检测的稳健解决方案。
Vue-cli 提供了开箱即用的功能。
来自vue-cli 文档