问题
有用户打开页面白屏,找到用户手机系统是iOS 8。在找到iOS 8进行测试后,发现是Promise报错。
思考
代码都通过Babel转义了,为何还会报错?查看Babel官网说明,如下图:
说明如果需要支持Promise,需要使用polyfill。在polyfill的说明里写到,最简单的方法就是在代码入口文件直接加入:
import "@babel/polyfill";
或者在webpack配置入口文件时加入:
module.exports = {
entry: ["@babel/polyfill", "./app/js"],
};
这样就能解决Promise问题,和其他一系列不支持的API的问题。但是这个polyfill文件足足有90多kb,但是我们的代码又没有完全用到所有的特性。
Presets & Plugins
在使用vuecli新建项目,并且使用webpack模版时,生成的.babelrc文件如下:
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 20 versions", "not ie <= 8", "safari 7"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime"]
}
presets代表配置一套plugins的组合,这个env是babel 6之前的组合,用来根据使用环境,自动加载需要的plugins。但是光是又env还不够,因为这个env并不会加载polyfill。所以在plugins里加入了transform-runtime。这个插件可以根据用户使用的API,动态加载这些API的polyfill。这里就解决了载入polyfill导致文件过大的问题。
但是看到这里,你是否和我有一个同样的疑惑,就是既然presets是某些plugins的集合,为了针对性编译和按需加载polyfill,为啥这两个需要同时配置呢?
在最新Babel 7文档中,Presets提供了@babel/preset-env。有了它就不再需要配置 plugins就能自动加载使用过的polyfill。比如进行如下配置:
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage"
}
]
]
}
最新的VueCli。创建新项目的时候,也使用了这个Presets,说明文档:https://cli.vuejs.org/zh/guide/browser-compatibility.html#polyfill
参考文献
https://babeljs.io/docs/en/babel-polyfill/
使用了 babel-plugin-transform-runtime 之后,还需要使用 es6-promise 吗