問題
有用戶打開頁面白屏,找到用戶手機系統是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 嗎