minimize默认为true,效果就是压缩js代码。在production模式,该配置会默认为我们压缩混淆代码,但这显然满足不了我们对于优化代码的诉求。
var UglifyJsPlugin = require('uglifyjs-webpack-plugin')
var OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = {
optimization: {
minimizer: [
// 自定义js优化配置,将会覆盖默认配置
new UglifyJsPlugin({
exclude: /\.min\.js$/, // 过滤掉以".min.js"结尾的文件,我们认为这个后缀本身就是已经压缩好的代码,没必要进行二次压缩
cache: true,
parallel: true, // 开启并行压缩,充分利用cpu
sourceMap: false,
extractComments: false, // 移除注释
uglifyOptions: {
compress: {
unused: true,
warnings: false,
drop_debugger: true
},
output: {
comments: false
}
}
}),
// 用于优化css文件
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessorOptions: {
safe: true,
autoprefixer: { disable: true },
mergeLonghand: false,
discardComments: {
removeAll: true // 移除注释
}
},
canPrint: true
})
]
}
}
UglifyJsPlugin经常用到 过滤掉本身已经是压缩的js文件,exclude: /\.min\.js$/
能够提升我们的编译效率以及避免二次混淆压缩而造成的未知bug。
ptimizeCssAssetsPlugin这款插件主要用来优化css文件的输出,默认使用cssnano,其优化策略主要包括:摈弃重复的样式定义、砍掉样式规则中多余的参数、移除不需要的浏览器前缀等。这段配置autoprefixer: { disable: true }
,禁用掉cssnano对于浏览器前缀的处理。
默认为false,runtime相关的代码(各个模块之间的引用和加载的逻辑)内嵌入每个entry。
runtimeChunck: {
name: () => "manifest"
}
我们可以配合InlineManifestWebpackPlugin插件将运行代码直接插入html文件中,因为这段代码非常少,这样做可以避免一次请求的开销,但是新版插件的配置和之前有些不太一样,接下来详细讲解一下如何配置。
var HtmlWebpackPlugin = require('html-webpack-plugin')
var InlineManifestWebpackPlugin = require('inline-manifest-webpack-plugin')
module.exports = {
entry: {
app: 'src/index.js'
},
optimization: {
runtimeChunk: 'single'
// 等价于
// runtimeChunk: {
// name: 'runtime'
// }
},
plugins: [
new HtmlWebpackPlugin({
title: 'fle-cli',
filename: 'index.html',
template: 'xxx',
inject: true,
chunks: ['runtime', 'app'], // 将runtime插入html中
chunksSortMode: 'dependency',
minify: {/* */}
}),
new InlineManifestWebpackPlugin('runtime')
]
}
这里有一个点要注意,InlineManifestWebpackPlugin插件的顺序一定要在HtmlWebpackPlugin之后,否则会导致编译失败。
默认为true,编译错误的时候是否不生成资源。
主要就是根据不同的策略来分割打包出来的bundle。
默认配置:
splitChunks: {
chunks: "async",
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
默认‘async’
//入口文件引入
import './a.js' //同步加载
import ('./b.js') //异步加载
// b.js引入
import 'vue'
打包出b和vue两个chunk。
all:
splitChunks:{
chunks:'all',//同时分割同步和异步代码,推荐。
cacheGroup:{//默认的规则不会打包,需要单独定义
a: {
test: /a\.js/,
chunks: "all",
name: "a",
enforce: true
}
}
}
initial:
splitChunks:{
chunks:'initial'//也会同时打包同步和异步,但是异步内部的引入不再考虑,直接打包在一起,会将vue和b的内容直接打包成chunk,
cacheGroup:{//默认的规则不会打包,需要单独定义
a: {
test: /a\.js/,
chunks: "all",
name: "a",
enforce: true
}
}
}
分割的js名称,默认为true,返回${cacheGroup的key} ${automaticNameDelimiter} ${moduleName},可以自定义。
最小公用模块次数,默认为1
都为字面意思,一般不建议改。
缓存策略,默认设置了分割node_modules和公用模块。内部的参数可以和覆盖外部的参数。
test 正则匹配文件
priority 优先级
reuseExistingChunk是否复用存在的chunk
cacheGroup:{
a: {
test: /a\.js/,//匹配规则
minChunks:2,//重写公用chunks的次数
chunks: "all",
name: "a",//重写文件名称
enforce: true //强制生成
}
}
比较优雅的分离打包配置:
splitChunks: {
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
minSize: 30000,
minChunks: 1,
chunks: 'initial',
priority: 1 // 该配置项是设置处理的优先级,数值越大越优先处理
},
commons: {
test: /[\\/]src[\\/]common[\\/]/,
name: 'commons',
minSize: 30000,
minChunks: 3,
chunks: 'initial',
priority: -1,
reuseExistingChunk: true // 这个配置允许我们使用已经存在的代码块
}
}
}
首先是将node_modules的模块分离出来,这点就不再累述了。异步加载的模块将会继承默认配置,这里我们就不需要二次配置了。
第二点是分离出共享模块,笔者认为一个优雅的项目结构,其公共代码(或者称为可复用的代码)应该是放置于同一个根目录下的,基于这点我们可以将src/common中的公用代码提取出来。