刚使用webpack4来构建Vue2的项目环境就遇到了一些内置插件失效和环境依赖库的更新的坑。
webpack4中环境及依赖库的部分版本要求
loader | 最低版本要求 | 功能说明 |
---|---|---|
vue-loader | 15.0.0 | 解析、编译vue单文件组件中的样式,需要配合vue-loader/lib/plugin插件使用,并内置css编译器 |
vue-style-loader | 4.1.0 | 解析、编译vue单文件组件中的样式 |
babel-loader | 7.1.3 | 对最新的ES语法进行转换 |
file-loader | 1.1.10 | 批量修改文件路径、或者指定编译后文件储存路径 |
eslint-loader | 2.0.0 | 代码检查 |
可能会有遗漏!!
webpack 4.X 相对与webpack 3.X的重大变更,不再支持部分插件,如js压缩,chunk分离及文件分离的一些插件。
失效的插件 | 类型 | 功能说明 |
---|---|---|
webpack.optimize.CommonsChunkPlugin | 内置插件 | 分离chunk。将多次出现的代码统一打包到一个文件中,Vue工程中用来打包vendor及manifest |
webpack.optimize.UglifyJsPlugin | 内置插件 | 压缩JS |
extract-text-webpack-plugin | loader | 分离文件。将部分代码或文件提出到单独文件中。Vue工程中常用来分离css并合并到一个指定文件中 |
使用 mini-css-extract-plugin 代替
webpack4.X之前的版本常用extract-text-webpack-plugin插件来分离合并css到指定文件中,在webpack4中也提供了@next
版本,但这里我并不使用,选择推荐的新的替代插件mini-css-extract-plugin来替代旧插件。
新插件与旧插件都需要在webpack的loader部分和plugin部分都进行配置,不同的是新插件提供了单独的loader,配置如下:
const MiniCssExtractPlugin=require("mini-css-extract-plugin");
module.exports={
...
module:{
rules:[
{
test: /\.css$/,
use:[
MiniCssExtractPlugin.loader,
"css-loader"
]
}
]
},
plugins:[
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash].css'
})
]
}
拆分 js 代码
这是webpack配置中很重要的一个环节,如果不对js代码进行拆分,公共库与入口代码将合并在一个js文件中,影响到浏览器缓存的合理性,页面资源的加载速度。所以,对js进行合理拆分,可以有效减小我们每次更新代码影响到的文件范围,保证了长缓存。
使用webpack3时,我们一般会提出manifest.js
(webpack运行时,即webpack解析其他bundle代码时)、vendor.js
(node_modules内的库)、main.js(项目业务代码)。在webpack3中使用webpack.optimize.CommonsChunkPlugin
插件进行提取。在webpack4中被完全废除了,官方推荐使用optimization配置项进行配置,当然,css拆分也可以使用optimization来配置项。
在optimization中有一个非常重要的一个插件spliltChunkPlugin,刚使用webpack4,我在splitChunk的使用还在摸索阶段,我也查看了很多别人的配置,有很多的疑问,自己记录一些用法,如果大家有更好的建议,欢迎评论区说出来。
先来过一遍参数
optimization:{
splitChunks:{
chunks:async,//表示显示块的范围,三个可选值:
//initial(初始块)、async(按需加载块)、all(默认,全部块)
minSize:0,//表示在分离前的最小模块大小,默认为0,最小为30000
minChunks:1,//表示分离前被引用次数,默认为1
maxAsyncRequests:1,//最大按需加载次数,最大异步加载次数,默认1
maxInitialRequests:1,//最大初始化加载次数,一个入口文件可以并行加载的最大文件数量,默认1
automaticNameDelimiter: '~',//打包分隔符,若改为'-'则分离后的js默认命名规则为[来源]-[入口key].js
name: function(){},//打包后的名称,此选项可接受函数,默认true,,由chunk和hash值自动生成,
//当存在匹配的缓存组时,命名使用缓存组中的name值,若不在则为[来源]~[入口key].js
cacheGroups:{//设置缓存chunks
priority: 0,//缓存组优先级
//当需要优先匹配缓存组的规则时,priority需要设置为正数,当需要优先匹配默认设置时,缓存组需设置为负数,0为两者分割线
default:{//设置缓存组默认配置,可通过default:false禁用默认缓存组,
//然后就可以自定义缓存组,将初始化加载时被重复引用的模块进行拆分
minChunks:2,//引用两次
priority:-20,//缓存组优先级为-20
reuseExistingChunk:true,//表示可以使用已经存在的块,即如果满足条件的块已经存在就是用己有的的,不再创建一个新的块
},
[key]:{//自定义缓存组,可以根据需求,自由创建
chunks:'initial',
test: /vue/,//正则规则验证,如符合就提取chunk放入当前缓存组,值可以是function、boolean、string、RegExp,默认为空
enforce: true//优先处理
}
}
}
}
splitChunks是webpack主模块的一个细分模块,功能上,splitChunksPlugins只能用于如何抽离公用代码,制定抽离公用代码与入口文件的规则,除了这功能外,splitChunksPlugins 再无其他功能
下面是一个抽离公用代码与业务代码的一个可复用配置:
optimization:{
splitChunks:{
//对entry进行拆分
chunks: 'all',
minSize: 30000,
cacheGroups:{
//比如你要单独把vue等官方库文件打包到一起,可以使用这个缓存组,如果要具体到库文件,可以单独给库文件写一个缓存组
vendor:{
test: /node_modules/,
priority: 10,
name: "vendor",
enforce: true
},
//这里定义分离前被引用过两次的文件,将其一同打包到common.js,最小为30kb
common:{
name: "common",
minChunks: 2,
minSize: 20000
}
}
}
}
关于更多配置方法,一步步的了解webpack4的splitChunksPlugin插件 里有详细介绍。
另外还有一个可配套使用的runtimeChunk插件,webpack会添加一个只包含运行时的额外代码块到每一个入口。(看场景使用,它会导致每个入口都加载多一份代码)
压缩js
webpack4的uglifyJsPlugin实际上在不设置任何环境变量的情况下,始终会有压缩代码的行为,导致编译耗时,解决方法就是配置不同的环境变量在开发环境的不要使用uglifyJsPlugin插件,webpack4于是提供了mode这个新增的选项,且默认值为production,在package.json文件中设置–mode=production模式则自动开启。
参阅资料