笔者最近从新复习了一遍 Webpack 核心功能,果真是温故而知新!这篇文章结合高级进阶之 Webpack 篇阅读效果更佳!javascript
思路:缩小搜索范围,减小没必要要的模块打包,加快构建(缓存,多线程)
缩少搜索范围:css
减小没必要要的模块打包:前端
注意:在 Webpack5 中已经不⽤ DllPlugin、DllReferencePlugin 了,⽽是⽤ HardSourceWebpackPlugin 替代vue
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
const plugins = [
new HardSourceWebpackPlugin(
)
]
复制代码
加快构建:java
代码压缩 :
node
使用 ParallelUglifyPlugin 插件:开启多线程对 js 文件压缩和缓存,删除多余的注释和 console.log
注意: 在生产环境下即配置中 mode 设置为 production,webpack 默认开启了 TerserWebpackPlugin 能够实现该功能,若是须要剔除调试代码能够自行配置,具体参考下面的 TerserWebpackPlugin 配置
webpack
代码分割缓存:
使用 optimization.splitChunks.cacheGroup 进行公共代码分割抽离和缓存 es6
Webpack4.0 以上版本在 mode 为 production 时,会自动开启 Tree Shaking 能力。默认 production mode 的配置以下:web
const config = {
mode: 'production',
optimization: {
usedExports: true,
minimizer: [
new TerserPlugin({...})
]
}
};
复制代码
"side effect(反作用)" 的定义是,在导入时会执行特殊行为的代码,而不是仅仅暴露一个 export 或多个 export。举例说明,例如 polyfill,它影响全局做用域,而且一般不提供 export。面试
解决反作用:经过 package.json 的 "sideEffects" 属性,来实现这种方式。
{
"name": "your-project",
"sideEffects": ["./src/some-side-effectful-file.js"]
}
复制代码
若是你的代码确实有一些反作用,能够改成提供一个数组:
{
"name": "your-project",
"sideEffects": ["./src/some-side-effectful-file.js"]
}
复制代码
如下内容来自字节前端面试题
注意:启动 HMR 后,css 抽离会不⽣效,还有不⽀持 contenthash,chunkhash
// 使用 ParallelUglifyPlugin 并行压缩输出的 JS 代码
new ParallelUglifyPlugin({
// 传递给 UglifyJS 的参数
uglifyJS: {
output: {
// 最紧凑的输出
beautify: false,
// 删除全部的注释
comments: false,
},
compress: {
// 在UglifyJs删除没有用到的代码时不输出警告
warnings: false,
// 删除全部的 `console` 语句,能够兼容ie浏览器
drop_console: true,
// 内嵌定义了可是只用到一次的变量
collapse_vars: true,
// 提取出出现屡次可是没有定义成变量去引用的静态值
reduce_vars: true,
}
},
}),
复制代码
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new UglifyJsPlugin({
test: /\.js(\?.*)?$/i, //测试匹配文件,
// include: /\/includes/, //包含哪些文件
// exclude: /\/node_modules/, //不包含哪些文件
//容许过滤哪些块应该被uglified(默认状况下,全部块都是uglified)。
//返回true以uglify块,不然返回false。
chunkFilter: chunk => {
// `vendor` 模块不压缩
if (chunk.name === "vendor") {
return false;
}
return true;
},
cache: false, //是否启用文件缓存,默认缓存在node_modules/.cache/uglifyjs-webpack-plugin.目录
parallel: true //使用多进程并行运行来提升构建速度
})
]
},
}
// 等价于
{
plugins: [
// 压缩JS文件
new UglifyJSPlugin({
test: /\.js(\?.*)?$/i, //测试匹配文件,
// include: /\/includes/, //包含哪些文件
// exclude: /\/node_modules/, //不包含哪些文件
//容许过滤哪些块应该被uglified(默认状况下,全部块都是uglified)。
//返回true以uglify块,不然返回false。
chunkFilter: chunk => {
// `vendor` 模块不压缩
if (chunk.name === "vendor") {
return false;
}
return true;
},
cache: false, //是否启用文件缓存,默认缓存在node_modules/.cache/uglifyjs-webpack-plugin.目录
parallel: true //使用多进程并行运行来提升构建速度,不支持 es6
}),
],
}
复制代码
// webpack.config.js
// 导入terser-webpack-plugin-->减小js体积(其中删除js的console.log和注释)
const TerserWebpackPlugin = require('terser-webpack-plugin');
// 实例化TerserWebpackPlugin对象
const terserPlugin = new TerserWebpackPlugin({
parallel: 4,
extractComments: true,
terserOptions: {
compress: {
warnings: false,
drop_console: true,
drop_debugger: true,
pure_funcs: ['console.log'] //移除console
}
}
});
module.exports = {
optimization: {
minimizer: [
// 只有打包环境为production时才能生效
terserPlugin
],
},
}
复制代码
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].css",
// chunkFilename: "[name].css",
disable: isDebug
}),],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
};
复制代码
splitChunks:{
cacheGroups: {
common:{
chunks: 'initial',
name:'Common', // 打包后的文件名
minSize: 0,
minChunks: 2 // 重复2次才能打包到此模块
},
vendor: {
priority: 1, // 优先级配置,优先匹配优先级更高的规则,不设置的规则优先级默认为0
test: /node_modules/, // 匹配对应文件
chunks: 'initial',
name:'Vendor',
minSize: 0,
minChunks: 1
}
}
}
复制代码
const path = require('path')
const webpack = require('webpack')
module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, '/')
},
devServer: {
hot: true
},
plugins:[
new webpack.HotModuleReplacementPlugin()
]
}
复制代码
若是不使用 HotModuleReplacementPlugin 能够直接 package.json 配置
"dev": "webpack-dev-server --hot --open"
复制代码