差异化服务

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

我们可以编写“未来派”的 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 则会以某种方式下载两个版本,然后再次下载模块版本。所有这些浏览器都很快就会消失,但不能忽视。仍然值得这样做吗?可能。我很有兴趣研究对抗这些缺陷的替代技术。