今天写代码真是行云流水,很快就搞完了,马上提交。下午测试告诉我,不能兼容 IE 浏览器。这不打开就是空白,F12 进去跳出一个醒目的错误:
出错:[vuex] vuex requires a Promise polyfill in this browser.
这不是 Vue 的锅,React 应用也会遇到兼容 IE 浏览器的问题。百度了一下,很快找到解决方案。只要在入口文件添加引入 babel-polyfill 就搞定了。出于好奇,我下午抽时间仔细研究了一下 babel。
Babel 主要用于在旧的浏览器或环境中将 es6+ 代码转换为向后兼容版本的 es5 代码,从而可以运行在低版本浏览器或其它环境中。箭头函数语法、sync 函数语法、class 定义类语法和解构赋值等都是 ES6 新增的语法。这些都可以用 Babel 进行语法转换。因为我们的还得借助 webpack。
一 . 安装依赖
安装依赖
npm install --D babel-core babel-loader babel-preset-env webpack
- 新建 main.js,添加如下代码:
Promise.resolve('ok').then(val => {
console.log(val);
});
- 创建 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
通过以下命令安装 polyfill
npm install --save-dev babel-polyfill
- 在应用程序的入口起点顶部或在 bundler 配置中添加它来使用它,如下代码:
import 'babel-polyfill';
Promise.resolve('ok').then(function (val) {
console.log(val);
});
Babel 会根据指定的浏览器兼容列表自动引入所有所需的 polyfill, 不管你代码中有没有使用。这种方式缺点也是很明显的:一次性引入了 ES6 的所有 polyfill, 打包后的 JavaScript 文件体积会偏大,大约有 102k。所以生产环境不建议导入整个 polyfill:尝试使用 useBuiltIns 选项或仅手动导入需要的 polyfill,如果你比较清楚依赖的话。
- 创建预设。在上述基础上,新建
.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。
评论 (0)