仅在需要时使用 Polyfill JavaScript

Avatar of Pascal Klau (@pascalaoms)
Pascal Klau (@pascalaoms)

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

以下是来自南德意志的实习生 Pascal Klau 的客座文章,他不喜欢不必要的 HTTP 请求和西兰花。Pascal 将解释如何以一种可能根本不需要使用它的方式使用 polyfill 服务。

情况

我们想用 ES6 语法 编写 JavaScript。但由于我们需要支持不理解 ES6 的旧版浏览器,因此需要处理这个问题。

这是标准流程:编写 ES6 → 将所有内容编译为 ES5(例如 Babel)→ 发送到浏览器。

这可能不再是最有效的方法。问题在于,我们强迫现代浏览器运行它们不需要的旧代码。 它们支持 ES6,那么我们能否向它们提供 ES6 呢?

更好的方法

有一个名为 Polyfill.io API 的 polyfill 项目可以在客户端对 ES6 代码进行 polyfill。

它还为一些 HTML 功能(如 <picture> 元素)实现了 polyfill。

来自其网站的描述

Polyfill.io 读取每个请求的 用户代理 (UA) 标头,并返回适合请求浏览器的 polyfill。根据您在应用中使用的功能定制响应 […]

它由 金融时报 开发,因此它具有一定的支持,我们可以相当肯定它不会消失。

有一点需要明确:Polyfill.io 提供对语法糖的支持。例如,类、增强的对象文字以及箭头函数之类的东西。您仍然需要编译器才能使用它们。

设置 Polyfill.io

将 Polyfill.io 添加到您的项目可以非常简单。将 CDN 托管的脚本添加到您的页面

<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>

运行脚本会输出 UA 和您想要的功能。

UA detected: chrome/56.0.0
Features requested: default

更改请求参数

有一些 选项 可以自定义您放入脚本源中的请求。

功能

要进行 polyfill 的浏览器功能列表。接受以逗号分隔的功能名称列表。可在 浏览器和功能页面 上查看可用的功能名称。

<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=fetch"></script>

在 Safari 10 中,脚本现在显示如下

Features requested: fetch

- setImmediate, License: CC0 (required by "Promise", "fetch")
- fetch

如果像 fetch 这样的功能依赖于像 Promise 这样的其他功能,Polyfill.io 会自动添加它

标志

  • always – 无论发出请求的用户代理是否需要,都应包含 Polyfill。
  • gated – 如果 polyfill 包含在捆绑包中,它将附带一个功能检测,只有在不存在原生 API 时才会执行 polyfill。
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=fetch&flags=gated"></script>

回调

加载 polyfill 后要调用的函数的名称。这仅仅是一种在 polyfill 加载后触发您自己代码的方式,旨在允许更轻松地使用 async 和 defer 属性异步加载 polyfill 服务。

问题

尽管这一切听起来都很好,但它仍然不完美。

现代浏览器不必加载 ES5,而是必须进行服务器往返行程(HTTP 请求)以检查是否需要 polyfill。

这让我非常苦恼,因此我开发了一个小项目来提供帮助。

更好的方法

设置动态 polyfill

我创建的 npm 包称为 dynamic-polyfill。它在进行任何服务器请求之前检查功能是否得到原生支持。

设置如下所示

import polyfill from 'dynamic-polyfill'

polyfill({
    fills: 'fetch, Promise',
    options: 'gated', // default: null
    minify: false,  // default: true
    afterFill() {
        main()
    }
})

function main() {
    // app code here
}

这将使用简单的语言执行如下操作

[window.fetch, window.Promise] 是否存在?

如果存在,则运行 afterFill() 回调。

如果不存在,则创建一个带有 async 属性的 <script> 标签,插入包含所有提供的选项的 Polyfill.io 链接,并在其加载完成后运行 afterFill() 回调。

注意:并非所有选项都得到支持,仅支持最重要的选项。

较小的占用空间

由于此模块缩小后小于 1KB并且没有任何依赖项,因此它在您的项目中占用空间非常小。

结论

为现代浏览器编写面向未来的高效 JavaScript。让 Polyfill.io 处理旧版浏览器。如果不需要,请不要执行额外的 HTTP 请求。

只需确保您有一些东西可以擦干这些喜悦的泪水。