筆者最近從新複習了一遍 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"
複製代碼