本文衔接上篇文章:
不睡觉的怪叔叔:webpack的模块热替换zhuanlan.zhihu.com一、为什么需要Babel?
由于某些浏览器不支持ES6,所以使用ES6写的JavaScript程序不能在这些浏览器中运行。
比如index.js中写一段ES6代码:
let set = new Set();
set.add(1);
set.add(2);
set.add(3);
然后进行打包:
现在这个程序在某些不支持ES6的浏览器中是不能运行的。
可以在webpack中使用babel来将ES6代码转换为ES5的代码。
二、babel的基本配置
首先安装babel-loader与@babel/core:
然后在webpack.config.js中进行相应的配置:
webpack.config.js:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const webpack = require('webpack');
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
entry: {
main: './src/index.js',
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
plugins:[
new HtmlWebpackPlugin({
filename: 'dist.html',
template: './src/template.html'
}),
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin() // 开启模块热替换
],
devServer: {
contentBase: './dist',
port: '8080',
hot: true, // 开启模块热替换
hotOnly: true
},
module: {
rules: [
{
rules: [
{
test: /.(png|svg|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
limit: 1024
}
}]
},{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
},{
// 针对babel的配置
rules: [{
test: /.js$/,
exclude: /node_modules/, // 无需对第三软件库进行转换,因为它们已经做了转换
loader: 'babel-loader'
}]
}
]
}
]
}
}
三、使用preset-env实现代码转换
目前已经做好了关于Babel的基础配置,但是现在Babel还不能对代码进行转换,还需要@babel/preset-env的帮助,它才能做从ES6到ES5的转换。
那么首先要安装@babel/preset-env:
然后再配置webpack.config.js:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const webpack = require('webpack');
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
entry: {
main: './src/index.js',
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
plugins:[
new HtmlWebpackPlugin({
filename: 'dist.html',
template: './src/template.html'
}),
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin() // 开启模块热替换
],
devServer: {
contentBase: './dist',
port: '8080',
hot: true, // 开启模块热替换
hotOnly: true
},
module: {
rules: [
{
rules: [
{
test: /.(png|svg|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
limit: 1024
}
}]
},{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
},{
// 针对babel的配置
rules: [{
test: /.js$/,
exclude: /node_modules/, // 无需对第三软件库进行转换,因为它们已经做了转换
loader: 'babel-loader',
options: {
presets: ["@babel/preset-env"]
}
}]
}
]
}
]
}
}
现在再打包代码:
检查打包出来的main.js可以发现ES6的let关键字被转换为ES5的var关键字:
现在已经将能转换为ES5的代码转换了,但是不支持ES6的浏览器仍然无法识别ES6的Set类,此时就要借助Babel的polyfill的帮助了。
四、使用polyfill补充代码
polyfill能为不支持ES6的浏览器补充ES6的相关代码。那么首先来安装polyfill:
然后修改index.js文件以导入polyfill补充的代码:
index.js:
import "@babel/polyfill";
let set = new Set();
set.add(1);
set.add(2);
set.add(3);
现在再次打包:
此时就导入了polyfill补充的代码了,可以发现main.js文件增加到了934kb。至此就兼容了那些不支持ES6的浏览器。
五、更多配置
Babel功能非常强大,配置也非常繁杂,这里说几个简单实用的配置。
5.1、使polyfill只补充相关代码
由于polyfill除了补充与我们业务代码相关的代码外,还会补充与我们业务代码无关的代码。
比如本例中polyfill除了补充Set类相关的代码外,还会补充其他ES6相关补全代码,所以致使main.js增加到934kb。
可以手动配置,来使polyfill只补充相关的代码。
修改webpack.config.js进行配置:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const webpack = require('webpack');
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
entry: {
main: './src/index.js',
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
plugins:[
new HtmlWebpackPlugin({
filename: 'dist.html',
template: './src/template.html'
}),
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin() // 开启模块热替换
],
devServer: {
contentBase: './dist',
port: '8080',
hot: true, // 开启模块热替换
hotOnly: true
},
module: {
rules: [
{
rules: [
{
test: /.(png|svg|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
limit: 1024
}
}]
},{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
},{
// 针对babel的配置
rules: [{
test: /.js$/,
exclude: /node_modules/, // 无需对第三软件库进行转换,因为它们已经做了转换
loader: 'babel-loader',
options: {
presets: [
[
"@babel/preset-env",
{
useBuiltIns: 'usage' // 只补充相关的代码
}
]
]
}
}]
}
]
}
]
}
}
index.js文件中可以不用手动导入@babel/polyfill,因为babel会自动导入:
index.js:
let set = new Set();
set.add(1);
set.add(2);
set.add(3);
再次打包:
可以发现main.js缩减为192kb。
5.2、指定适配的浏览器版本
可以指定适配的浏览器版本,以使Babel针对该浏览器版本进行ES6到ES5的转换。
配置webpack.config.js:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const webpack = require('webpack');
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
entry: {
main: './src/index.js',
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
plugins:[
new HtmlWebpackPlugin({
filename: 'dist.html',
template: './src/template.html'
}),
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin() // 开启模块热替换
],
devServer: {
contentBase: './dist',
port: '8080',
hot: true, // 开启模块热替换
hotOnly: true
},
module: {
rules: [
{
rules: [
{
test: /.(png|svg|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
limit: 1024
}
}]
},{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
},{
// 针对babel的配置
rules: [{
test: /.js$/,
exclude: /node_modules/, // 无需对第三软件库进行转换,因为它们已经做了转换
loader: 'babel-loader',
options: {
presets: [
[
"@babel/preset-env",
{
useBuiltIns: 'usage', // 只补充相关的代码
targets: {
chrome: '67' // 指定适配的浏览器版本
}
}
]
]
}
}]
}
]
}
]
}
}
5.3、将配置项单独放在一个文件中
当Babel配置的中的opions项中的配置越来越多时,最好使用单独的文件来放置这些配置。
在webpack-demo根目录中创建一个文件.babelrc,并将options中的内容放进去:
.babelrc:
{
presets: [
[
"@babel/preset-env",
{
useBuiltIns: 'usage', // 只补充相关的代码
targets: {
chrome: '67' // 指定适配的浏览器版本
}
}
]
]
}
再次打包:
配置生效!