本篇文章参考以下博文
前言
最近在打包项目的时候,文件是打出来了,但是打出来的文件体积太大,主要是没几行的代码居然打出来了几百 KB ,这就有点离谱了。
查看了一下打包出来的文件,发现了一堆没用的 ES6 兼容内容,代码里根本没有使用,居然一股脑的全部打包进去了。
重新检索了一遍打包配置,发现是其中一项对于 js 的兼容处理有问题。记录一下,提醒自己同样的错误不再次出现。
JS兼容处理的三种方式
babel-loader
这种方式的配置只需要增加一个 loader 即可,不过下载依赖包的时候需要三个,分别是 babel-loader @babel/core @babel/preset-env
配置的时候注意, test 检测的是 .js 结尾的文件,需要排除 node_modules 里面的内容。
完整的配置如下:
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.export = {
entry: './src/js/index.js',
output: {
filename: 'js/bulit.js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
preset: ['@babel/preset-env']
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
mode: 'development'
}
这种方式有一个缺点,那就是只能转换基本语法,比如 let const 箭头函数等。对于一些高级语法,比如 Promise 之类的,就无法进行转换了。
@babel/polyfill
为了解决兼容所有 js 语法的问题,就需要一个新的方法,这个方法不需要在 webpack 中进行配置,下载完依赖后,直接在 js 文件中 import 引入即可。
import '@babel/polyfill';
这个方法的好处是可以转换所有 es6 的新特征,缺点就是,有些没有用到的也会进行转换,比如我项目里只用了一些基本语法,但是这个包还是会吧所有关于 es6 的兼容处理都加载一遍。
这么做的后果就是打出来的包,会很大,原本只有 4KB 的包,能打出来 400KB ,体积太大,而且造成性能浪费。
core-js
以上两种方法都存在缺点,那么第三种就应运而生,按需加载 js 。
使用方法类似第一种,不过配置的时候需要做一些修改:
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.export = {
entry: './src/js/index.js',
output: {
filename: 'js/bulit.js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
preset: [
[
'@babel/preset-env',
{
//按需加载
useBuiltIns: 'usage',
//指定 core-js 版本
corejs: {
version: 3
},
//指定兼容性做到那个版本的浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]
]
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
mode: 'development'
}
core-js 基本上是现在最终的解决方案,按需加载,超级灵活,可以指定兼容到的浏览器版本。