babel/polyfill

浏览器兼容性

browserslist

package.json 文件里的 browserslist 字段 (或一个单独的 .browserslistrc 文件),指定了项目的目标浏览器的范围。这个值会被 @babel/preset-env 和 Autoprefixer 用来确定需要转译的 JavaScript 特性和需要添加的 CSS 浏览器前缀。

现状

我们想要用 ES6 语法来写 JavaScript。然而由于我们需要兼容老版本的浏览器,那些浏览器不支持 ES6,我们需要解决这个问题。

有一个标准的做法是:写 ES6 代码 → 将所有代码编译成 ES5 的(比如通过 Babel)→ 再将编译后的代码加载到浏览器执行。

这可能已经不再是最有效率的方式了。因为用这种方式,我们强制最新的浏览器运行旧代码,实际上它们完全可以运行最新的代码。它们支持 ES6,我们难道不能直接给它们 ES6 代码吗?

改进方式

有一个 polyfill 项目叫做 Polyfill.io API,它可以通过 polyfill 方式在客户端执行 ES6 代码。
它也实现了一些 HTML 特性的 polyfill,比如 元素。
下面是他们网站的描述:

Polyfill.io 读取每个请求的 User-Agent(UA) 头,并生成适合于该浏览器的 polyfill ,基于你的应用所使用的特性发回必要的代码。[...]

要添加 Polyfill.io 到你的项目里非常简单。将托管在 CDN 的脚本添加到你的页面上:


运行脚本将返回 UA 和你想要的特性。

UA detected: chrome/56.0.0
Features requested: default

@babel/polyfill模块

@babel/polyfill模块用于模拟完整的 ES2015+ 环境。

这意味着你可以使用诸如 PromiseWeakMap 之类的新的内置组件、 Array.fromObject.assign 之类的静态方法、 Array.prototype.includes 之类的实例方法以及生成器函数(generator functions)

useBuiltIns参数

npm install --save @babel/polyfill

注意,使用 --save 参数而不是 --save-dev,因为这是一个需要在你的源码之前运行的 polyfill。

我们使用 env preset 提供的 "useBuiltIns" 参数,当此参数设置为 "usage" 时,就只包含你所需要的 polyfill。

const presets = [
  [
    "@babel/env",
    {
      targets: {
        edge: "17",
        firefox: "60",
        chrome: "67",
        safari: "11.1",
      },
      useBuiltIns: "usage",
    },
  ],
];

module.exports = { presets };

Babel 将检查你的所有代码,以便查找目标环境中缺失的功能,然后只把必须的 polyfill 包含进来。示例代码如下:

Promise.resolve().finally();

将被转换为(由于 Edge 17 没有 Promise.prototype.finally):

require("core-js/modules/es.promise.finally");

Promise.resolve().finally();

如果我们不使用 env preset 的 "useBuiltIns" 参数(即设置为 "usage"),那么我们必须在所有代码之前通过 require 加载一次完整的 polyfill。

你可能感兴趣的:(babel/polyfill)