webpack4配置总结(六)

上一篇整理了plugins的配置。这篇开始整理webpack其他的一些配置项。

resolve

resolve是指定webpack打包构建过程中模块如何解析的相关配置。比如代码中的模块路径怎么解析,文件名怎么解析。这里简单整理一下两个配置项extensionsalias

extensions

extensions是用来解析文件名的。我们一般会在引用文件是省略掉一些文件的扩展名,那么配置这一项可以告诉webpack,在解析省略扩展名的文件时,去匹配什么扩展名。这个配置项接受一个数组,这个数组列举了需要匹配的扩展名。匹配上顺序是数组从左到右,即优先匹配数组左侧的元素。如配置了['.js', '.vue'],则当遇到/src/main这个文件名时,会先在src目录下匹配是否存在main.js文件,有则解析这个文件,没有则继续匹配判断是否存在main.vue文件。

1
2
3
resolve: {
extensions: ['.js', '.vue'], // 自动解析确定的扩展名
},

alias

alias是用来创建importrequire的别名,换言之,我们可以通过别名来压缩长路径。比如说,我们需要在文件中引入一个src目录下另一个目录中的文件,如果文件的层级很深,可能会写出import xxx from '../../../components/btn.vue'。通过配置别名,我们可以把@作为src目录的别名,这样就可以把前面的代码改写成import xxx from '@/components/btn.vue'

1
2
3
4
5
6
7
8
9
10
resolve: {
alias: { // 配置模块引入中的别名
'vue': 'vue/dist/vue.esm.js',
'@': path.join(__dirname, "../src"),
'@images': path.join(__dirname, "../src/common/images"),
'@components': path.join(__dirname, "../src/components"),
'@common': path.join(__dirname, "../src/common"),
'@api': path.join(__dirname, "../src/api"),
}
},

devServer

devServer这个配置项是需要安装webpack-dev-server来启用的,用来配置本地服务器的。只要安装了webpack-dev-server就可以使用它来在本地启动服务器进行项目本地调试。不过还是有一些可配置的选项的。

port可以配置端口,默认是8080,如果有多个本地项目运行占用了8080端口,会自动后移端口号。compress为配置是否启用gzip压缩,可以提升返回页面的速度。contentBase为配置webpack启动在哪个目录下启动服务。historyApiFallback为配置是否启用HTML5 History API,当出现404响应时会被替代为index.html,这一项可以配置布尔值,也可以进一步配置选项。还有其他的选项可以到官网上查看。

1
2
3
4
5
6
7
devServer: {
// 开发服务的配置
// port: 8080, // 不配置默认为8080,如果同时有多个本地项目运行且占用8080端口,会自动改端口
compress: true, // 启用gzip压缩 可以提升返回页面的速度
contentBase: path.resolve(__dirname, '../dist'), // webpack 启动服务会在dist目录下
historyApiFallback: true // 当使用 HTML5 History API 时,任意的 404 响应都可能需要被替代为 index.html
}

optimization

optimization是webpack的优化配置项,从webpack4开始,用来根据不同的打包环境(设置mode)对打包进行优化,而且支持手动配置及重写的。optimization的可选配置项,有些是设置值,有些是通过引入插件来实现的,所以这里会结合实际情况来整理一些配置项的使用方法。

minimizer

minimizer支持用户自定义打包压缩的插件,并替换掉webpack默认的压缩插件。一方面,用户可以自行选择压缩js代码的插件,另一方面,项目中还有其他编程语言需要使用压缩插件。webpack打包压缩默认只压缩js代码,但是css代码并没有压缩。而如果指定了压缩css代码的插件,那么原有的压缩js代码的功能就会被覆盖掉,所以同时也需要指定压缩js代码的插件。这里就使用到了optimize-css-assets-webpack-pluginterser-webpack-plugin

optimize-css-assets-webpack-plugin

optimize-css-assets-webpack-plugin是用来压缩优化css代码的插件,默认使用cssnano来压缩优化。它接收5个配置项,分别是:assetnameRegExp(一个匹配文件的正则表达式),cssProcessor(自定义用于优化压缩css的处理器),cssProcessorOptions(传递给css处理器的选项), cssProcessorPluginOptions(传递给css处理器的插件选项)及canPrint(一个布尔值,指定是否可以将信息打印到控制台)。

terser-webpack-plugin

terser-webpack-plugin是用来压缩js代码的插件。因为配置了minimizer,覆盖了默认的压缩功能,所以也需要配置压缩js的插件。这个插件有比较多的配置项,不过不配置也可以达到最佳的优化效果,所以需要配置可以去看官方文档。

1
2
3
4
5
6
optimization: {
minimizer: [
new OptimizeCSSAssetsPlugin(), // 压缩css,但使用之后js文件也需要手动压缩
new TerserWebpackPlugin(), // 压缩js
]
},

runtimeChunk

runtimeChunk是用来优化持久化缓存的。从我的理解来说,runtimeChunk默认是false,意思是webpack打包构建之后,会各个模块之间的引用和加载的逻辑内嵌到模块中,如果某个模块发生改变时,会导致除了除此之外引用及加载的模块一并发生改变,导致缓存失败。

如果设置为true(也可以是一个object配置对象来表示启用)或者multiple,会在打包构建之后,给每个入口文件都生成一个对应的runtime文件,里面会存放有生成一个包含chunk映射关系的表。一旦某个模块发生改变时,只会修改该模块跟对应的runtime文档,不会影响到引用及加载的模块,实现持久化缓存。

如果设置single,则表示在打包构建之后,只生成一个runtime文件,存放项目所有chunk映射关系表。

如果是一个object配置对象,里面可以配置name来指定生成的runtime文件的命名。

splitChunks

splitChunks这个配置项是用来定义使用什么策略拆分打包模块。里面有非常多的可配置选项来制定你的拆分打包策略。下面来一个个的介绍配置项:

chunks

chunks用来指定哪些模块会应用优化。支持配置三个值allasyncinitialall是指同时拆分同步和异步代码,async是默认值,指只拆分异步代码,initial虽然也会同时拆分同步和异步代码,但是异步代码内容不会再拆分。

minSize

minSize用来指定文件超过minSize值则会启用抽离。

maxSize

maxSize用来指定拆分的模块最大尺寸,不过有些模块即使大小超过maxSize,但是拆分不一定是最佳选择。

minChunks

minChunks指定模块至少达到minChunks引用次数才会启用抽离。

maxAsyncRequests

maxAsyncRequests指定并行请求数量

maxInitialRequests

maxInitialRequests指定首屏并行请求数量

automaticNameDelimiter

automaticNameDelimiter指定拆分模块的命名的界定符。webpack默认拆分模块的命名会使用模块的来源和名称使用界定符来生成。默认界定符为~

automaticNameMaxLength

automaticNameMaxLength指定拆分模块的命名的最大长度。

cacheGroups

cacheGroups用来自定义缓存组。cacheGroups接受一个对象,这个对象的键名为缓存组组名,值是一个对象,可以设置一系列相关配置。如果需要禁用默认缓存组,可以在cacheGroups下设置default: false。缓存组有以下配置项:

priority是用来设定缓存组的优先级。因为一个模块可以属于多个缓存组,所以模块会根据缓存组的优先级来选定放在哪个缓存组中。

reuseExistingChunk是用来指定当前模块包含从主模块中拆分出来的模块,是否重用该模块。

test是用来指定缓存组选择的模块,接受一个正则表达式来匹配模块名或路径。

filename指定缓存组模块的文件名占位符

enforce指定webpack是否忽略splitChunks.minSizesplitChunks.minChunkssplitChunks.maxAsyncRequestssplitChunks.maxInitialRequests,只创建缓存组模块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
optimization: {
splitChunks: {
chunks: 'all', // 'async' 默认支持异步的代码分割 如import()
minSize: 30000, // 文件超过30k,就会抽离
maxSize: 0,
minChunks: 1, // 最少模块引用1次才抽离
maxAsyncRequests: 6, // 最多6个请求
maxInitialRequests: 4, // 最多首屏加载4个请求
automaticNameDelimiter: '~', // 抽离文件名***~a~b,代表a,b都有引用,使用~来分隔
automaticNameMaxLength: 30, // 最长名字大小
cacheGroups: { // 缓存组
vues: {
test: /[\\/]node_modules[\\/]\/vue|vue-router|vuex/,
priority: 1 // 优先级
},
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 1, // 至少引用1次
priority: -20,
reuseExistingChunk: true
}
}
},
},

至此,整理完了我的模板项目的webpack配置。

这套webpack配置我也尝试改成基于React的项目,也能成功的跑通。当然,webpack的配置不一定每个项目都相同,都是有不同的需求跟优化的空间。目前我这个模板项目还是有一些地方可以再优化,或者在我更深入了解webpack之后可能又会有更好的配置。之后还有webpack5,也是以后需要去研究应用的内容。