分类
Javascript

使用babel-polyfill

今天写代码真是行云流水,很快就搞完了,马上提交。下午测试告诉我,不能兼容IE浏览器。这不打开就是空白,F12进去跳出一个醒目的错误:[vuex] vuex requires a Promise polyfill in this browser.这不是Vue的锅,React应用也会遇到兼容IE浏览器的问题。百度了一下,很快找到解决方案。只要在入口文件添加引入babel-polyfill就搞定了。出于好奇,我下午抽时间仔细研究了一下babel。

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

一、安装依赖

1、安装依赖

npm install --save-dev babel-core babel-loader babel-preset-env webpack

2、新建main.js,添加如下代码

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

3、创建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, 打包后的js文件体积会偏大,大约有102k。所以生产环境不建议导入整个polyfill:尝试使用useBuiltIns选项或仅手动导入需要的polyfill,如果你比较清楚依赖的话。

3. 创建预设。在上述基础上,新建.babelrc 文件(或者使用你的 package.json 文件)。配置preset-env,配置需要兼容的浏览器列表,指定useBuiltins选项为true。

{
  "presets": [
    [
      "env",
      {
        "targets": {
          "browsers": [
            "ie >=10"
          ]
        },
        "useBuiltIns": true
      }
    ]
  ]
}

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

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

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

注意:

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