使用 babel-polyfill

Flying
2017-07-28 / 0 评论 / 114 阅读 / 正在检测是否收录...

今天写代码真是行云流水,很快就搞完了,马上提交。下午测试告诉我,不能兼容 IE 浏览器。这不打开就是空白,F12 进去跳出一个醒目的错误:

出错:[vuex] vuex requires a Promise polyfill in this browser.

这不是 Vue 的锅,React 应用也会遇到兼容 IE 浏览器的问题。百度了一下,很快找到解决方案。只要在入口文件添加引入 babel-polyfill 就搞定了。出于好奇,我下午抽时间仔细研究了一下 babel。

babel.svg

Babel 主要用于在旧的浏览器或环境中将 es6+ 代码转换为向后兼容版本的 es5 代码,从而可以运行在低版本浏览器或其它环境中。箭头函数语法、sync 函数语法、class 定义类语法和解构赋值等都是 ES6 新增的语法。这些都可以用 Babel 进行语法转换。因为我们的还得借助 webpack。

一 . 安装依赖

  1. 安装依赖

    npm install --D babel-core babel-loader babel-preset-env webpack
  2. 新建 main.js,添加如下代码:
Promise.resolve('ok').then(val => {
  console.log(val);
});
  1. 创建 webpack.config.js 并运行。
module.exports = {
  entry: ['./main.js'],
  output: {
    filename: 'bundle.js',
  },
  module: {
    rules: [{
      test: /\.js$/,
      loader: "babel-loader",
      exclude: /node_modules/
    }]
  }
}

运行正确如下面代码输出:

Promise.resolve('ok').then(function(val) {
  console.log(val);
});

可以看到代码中的箭头函数转换为 ES5 兼容的函数表达式了,但 Promise 没有转换。这样的代码在 IE 上是不能运行的。原来 Babel 只进行语法转换(如箭头函数)。新的全局变量,如 Promise 或新的原生方法,如 String.padStart(left-pad)这些新的 API 就转不了,得借助 babel polyfill 来补齐 API,polyfill 顾名思义这是这个意思。

二 . 使用 babel-polyfill

  1. 通过以下命令安装 polyfill

    npm install --save-dev babel-polyfill
  2. 在应用程序的入口起点顶部或在 bundler 配置中添加它来使用它,如下代码:
import 'babel-polyfill';
Promise.resolve('ok').then(function (val) {
  console.log(val);
});

Babel 会根据指定的浏览器兼容列表自动引入所有所需的 polyfill, 不管你代码中有没有使用。这种方式缺点也是很明显的:一次性引入了 ES6 的所有 polyfill, 打包后的 JavaScript 文件体积会偏大,大约有 102k。所以生产环境不建议导入整个 polyfill:尝试使用 useBuiltIns 选项或仅手动导入需要的 polyfill,如果你比较清楚依赖的话。

  1. 创建预设。在上述基础上,新建 .babelrc 文件(或者使用你的 package.json 文件)。配置 preset-env,配置需要兼容的浏览器列表,指定 useBuiltins 选项为 true
{
  "presets": [
    [
      "env",
      {
        "targets": {
          "browsers": [
            "ie >=10"
          ]
        },
        "useBuiltIns": true
      }
    ]
  ]
}

这样按需(按照指定的浏览器环境所需)引入 polyfill, 一定程度上减少了不必要 polyfill 的引入。打包后的 JavaScript 文件体积会小不小,大约 78K。

事实上,只要使用了 babel-polyfill,就会污染了全局对象,可以使用 transform-runtime 插件来解决这一问题。限于篇幅,下次再讲。

这意味着你将不能使用上文中提到的实例方法,比如 Array.prototype.includes

注意:通常情况下,我们可能不需要 babel-polyfill 或者运行时插件,这取决于你实际想用 ES2015 中的哪些个方法。可能只想载入某些你正在使用的特定 polyfills(比如 Object.assign),或者只是记录加载内库存时包含特定的 polyfills。
4

评论 (0)

取消