在咱們的項目中,若是使用了es6的語法和API時就要用到babel對這些語法進行轉化,使代碼能夠在低版本的瀏覽器上正常運行。css
假若有一段es6代碼(main.js):webpack
async function f() {
return await 123;
}
f().then(v => console.log(v))
console.log(Object.values({ 1: 2 }));
console.log(Array.isArray([]));
console.log([1, 2, 3].includes(3));
複製代碼
package.jsones6
{
"name": "babel-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack --config webpack.config.js",
"dev": "webpack-dev-server --open"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.4.5",
"@babel/plugin-transform-runtime": "^7.4.4",
"@babel/preset-env": "^7.4.5",
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "^24.8.0",
"babel-loader": "^7.1.4",
"css-loader": "^1.0.1",
"regenerator-runtime": "^0.13.2",
"webpack": "^4.34.0",
"webpack-cli": "^3.3.4"
},
"dependencies": {
"@babel/polyfill": "^7.4.4",
"@babel/runtime": "^7.4.5",
"@babel/runtime-corejs2": "^7.4.5"
}
}
複製代碼
webpack4的配置:web
const path = require('path');
module.exports = {
mode: "development",
devtool: "inline-cheap-module-source-map",
entry: {
app: ['./main.js']
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './dist'),
},
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader']
}
]
}
};
複製代碼
註釋掉rules,打包後在IE瀏覽器運行報錯 npm
{
"presets": [["@babel/preset-env"]],
}
複製代碼
由於單獨使用babel-loader是不能對es6的語法進行解析的,須要配合babel-preset-env。 繼續打包運行json
依然報錯,可是報錯信息發生了變化,由於babel-loader只會對es6的語法進行解析,例如箭頭函數。若是要解析es6的API方法就要引入babel-polyfill或者babel-runtime。promise
babel-polyfill瀏覽器
模擬一個完整的es2015+環境,用於應用程序的開發而不是庫文件,可使用Promise之類的新的內置組件和Array.from和Object.assign之類的靜態方法和 Array.prototype.includes等實例方法,polyfill將添加到全局範圍和本地原型中,所以會污染全局變量。bash
引入babel-polyfill的四種方式:babel
{
"presets": [["@babel/preset-env", {"useBuiltIns": "entry", "corejs": 2}]],
}
複製代碼
並在main.js頂部使用import "@babel/polyfill"
{
"presets": [["@babel/preset-env", {"useBuiltIns": false}]],
}
複製代碼
在webpack.config.js中入口配置:
entry: {
app: ['@babel/polyfill', './main.js']
},
複製代碼
4.設置.babelrc,無需引用@babel/polyfill
{
"presets": [["@babel/preset-env", {"useBuiltIns": "usage", "corejs": 2}]],
}
複製代碼
該配置會自動加載項目中須要的polyfill,而不是所有引入。
打包以後bundle.js大小的比較:
打包以前:
使用前三種引用方式:
使用第四種引用方式:
可見前三種屬於所有引用,第四種屬於按需引用。固然也能夠從安裝包裏找到所需的墊片手動導入。
babel-runtime
項目中安裝依賴包:
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
複製代碼
babel-runtime爲生產依賴,transform-runtime爲開發依賴,從這裏便可看出,babel-runtime中包含了全部的核心幫助函數。使用babel-runtime的兩種方式
import Promise from "babel-runtime/core-js/promise";
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi!');
複製代碼
項目中只使用了Promise,因此只須要引入Promise的幫助函數便可。查看打包以後的bundle.js,能夠看到Promise被重寫,而不是和babel-polyfill同樣放在global上。可是當項目文件比較多,使用的es6 API也比較多時,手動引入就變的比較繁瑣。這時就須要transform-runtime插件了,該插件會分析項目代碼,自動的引入所需的墊片APIs。使用方法:在.babelrc中配置:
{
"plugins": [["@babel/plugin-transform-runtime", {"corejs": 2}]]
}
複製代碼
並安裝依賴:
npm install --save @babel/runtime-corejs2
複製代碼
去掉手動引入的core-js/promise文件,打包。能夠看到打包完以後的文件和手動引入的文件大小相同,而且均可以正常在IE中運行。transform-runtime的配置參數corejs默認值爲false,假定用戶將引入全部須要使用的幫助文件,因此爲了達到自動引入的效果須要手動的改成2.不然不會解析es6的代碼。
babel-runtime爲你的代碼提供了一個沙盒環境,因此不會像babel-polyfill同樣污染全局變量,所以適用於開發組件庫。可是babel-runtime不能模擬實例方法,即內置對象原型上的方法,例如Array.prototype.concat。
可是若是babel版本>=7.4.0,設置corejs: 3。一樣安裝依賴
npm install --save @babel/runtime-corejs3
複製代碼
在IE中[1, 2, 3].includes(3)方法能夠正常執行。可見core: 3在core: 2的基礎上解決了babel-runtime不能解析實例方法的弱點。