上一篇文章介绍了最基本的Webpack配置,可以满足一个前端项目最基本的构建和打包需求。 本文在基本配置上,增加更高级的配置,包括多入口处理、压缩CSS、公共代码和第三方库打包优化和懒加载。
多入口处理
上一节介绍的配置都是单一入口文件,最终打包产出单一HTML文件。 如果想要最终产出多个HTML文件,那么就需要配置多入口。
1. 配置多个entry
之前在基本配置里,入口配置是放在webpack.base.conf.js
下:
entry: path.join(srcPath, 'index')
这里的意思是把src/index.js
作为打包构建的唯一入口文件。
如果要配置多入口,此时的entry
不再是一个字符串,而是一个对象,每一对键值对就是一个入口,其中的key是每个入口文件形成chunk
后的唯一标识,下面配置plugins
和output
时会利用到这些标识:
entry: {
index: path.join(srcPath, 'index.js'),
other: path.join(srcPath, 'other.js')
}
2. 配置HtmlWebpackPlugin
上一节说到,HtmlWebpackPlugin
是用来生成最终的HTML文件,所有打包后的bundle文件都会以script标签的形式存在于这个HTML文件内加载出来。
一个HtmlWebpackPlugin
配置就会生成一个HTML文件,所以想要最终有多个HTML文件,就需要配置多个HtmlWebpackPlugin
。
template
:模板html文件filename
:打包后的文件名chunks
:当前页面需要引用的chunks
标识,默认全部引用
plugins: [
// 多入口 - 生成 index.html
new HtmlWebpackPlugin({
template: path.join(srcPath, 'index.html'),
filename: 'index.html',
// chunks 表示该页面要引用哪些 chunk (即上面的 index 和 other),默认全部引用
chunks: ['index'] // 只引用 index.js
}),
// 多入口 - 生成 other.html
new HtmlWebpackPlugin({
template: path.join(srcPath, 'other.html'),
filename: 'other.html',
chunks: ['other'] // 只引用 other.js
})
]
3. 配置输出output
上一节的基本配置我们是这么配置output
的:
output: {
filename: 'bundle.[contentHash:8].js', // 打包代码时,加上 hash 戳
path: distPath,
},
这样的配置会导致最终所有打包后的bundle文件都叫bundle.xxx.js
文件,不好区分是哪个入口。
所以输出配置这里要利用入口文件的chunk
标识,对输出的bundle
文件进行命名:
output: {
filename: '[name].[contentHash:8].js', // name 即多入口时 entry 的 key
path: distPath,
},
压缩CSS
在上一节基础配置里,我们是通过css-loader
、style-loader
等将CSS文件最终处理为style
样式,最终以style
的方式注入到最终打包形成的JS文件。
但是这样的做法会导致最终打包出来的JS文件比较大,初次加载的时间比较长。
所以对于CSS文件,考虑有两点优化的地方:
- 要从JS文件中抽离出来,JS文件和样式文件分别引入,加快加载速度
- 对CSS代码进行产出优化,对它们进行压缩,减小打包后的体积
1. 使用mini-css-extract-plugin.loader
解析,抽离CSS文件
我们可以使用mini-css-extract-plugin
实现抽离CSS目标,只要将之前使用style-loader
,改为使用MiniCssExtractPlugin.loader
即可。
使用mini-css-extract-plugin
好处:
- CSS不再通过
style
的方式引入,打包过后的js文件也不会有css相关的内容 - 所有的CSS都通过
link
标签加载,速度更快
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// ...
module: {
rules: [
// 抽离 css
{
test: /\.css$/,
loader: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
},
// 抽离 less --> css
{
test: /\.less$/,
loader: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
'postcss-loader'
]
}
]
},
2. 利用缓存的CSS文件
利用hash给打包后的CSS文件进行命名,利用浏览器缓存策略,命中名字的CSS文件不会重新加载,加快加载速度。
plugins: [
new CleanWebpackPlugin(), // 会默认清空 output.path 文件夹
new webpack.DefinePlugin({
// window.ENV = 'production'
ENV: JSON.stringify('production')
}),
// 设置打包后的CSS文件名,利用缓存
new MiniCssExtractPlugin({
filename: 'css/main.[contentHash:8].css'
})
],
3.optimize-css-assets-webpack-plugin
对CSS压缩
optimize-css-assets-webpack-plugin
主要的压缩策略是删除CSS文件里的空格和注释。
optimization: {
minimizer: [
new TerserJSPlugin({}),// 压缩JS
new OptimizeCSSAssetsPlugin({})// 压缩 css
],
}
抽离公共代码和第三方代码
我们在开发中,经常会抽取复用的公共代码,以及第三方库,通过import
的方式引入,减少重复代码,提升开发效率。
但是在打包过程中,Webpack会解析文件的引入,会把引入的文件也打包,这样就造成了公共的代码的重复打包,给打包后的文件增加了不必要的体积。
所以对于公共代码,我们可以考虑将其分割抽离出来,形成一个个个单独的chunk
,然后在入口配置时决定每个入口使用哪些chunk
,这样可以减少重复打包,实现按需加载。
1. 分割代码块
通过在optimization
设置splitChunks
去分割代码块,可以将第三方库代码和公共代码分别分割成一个chunk
。
配置要点:
- 在
cacheGroups
里去定义分割标准,其中的key
就是这个chunk
的名字 test
字段配置chunk
的文件范围minSize
字段决定体积规则,minChunks
字段决定复用次数规则,即只有超过minSize
的体积和复用超过minChunks
次才的代码,才会被抽离成相应的chunk
priority
字段决定当前抽离规则的优先级,数值越大,优先级越高
optimization: {
// 分割代码块
splitChunks: {
chunks: 'all',
// 缓存分组
cacheGroups: {
// 第三方模块
vendor: {
name: 'vendor', // chunk 名称
priority: 1, // 权限更高,优先抽离
test: /node_modules/,
minSize: 0, // 大小限制
minChunks: 1 // 最少复用过几次
},
// 公共的模块
common: {
name: 'common', // chunk 名称
priority: 0, // 优先级
minSize: 0, // 公共模块的大小限制
minChunks: 2 // 公共模块最少复用过几次
}
}
}
}
2. 配置入口
在设置完代码分割规则后,需要在入口配置,决定每个入口分别使用哪些chunk
,实现按需加载。
plugins: [
// 多入口 - 生成 index.html
new HtmlWebpackPlugin({
template: path.join(srcPath, 'index.html'),
filename: 'index.html',
// chunks 表示该页面要引用哪些 chunk,默认全部引用
chunks: ['index', 'vendor', 'common'] // 要考虑代码分割
}),
// 多入口 - 生成 other.html
new HtmlWebpackPlugin({
template: path.join(srcPath, 'other.html'),
filename: 'other.html',
chunks: ['other', 'common'] // 考虑代码分割
})
]
上面配置的chunks
数组中, vendor
和common
是我们在optimization.splitChunks
分割的chunk
,那么剩下的index
和other
是哪儿来的?
别忘了,我们在多入口配置里讲过,配置入口entry
也会形成chunk
,所以这里的index
和other
,就是在配置多入口时的两个chunk
。
总结一下会形成chunk
的地方:
entry
optimization.splitChunks
懒加载
通过使用webpack的'dynamic import', 可以将打包的代码分割成不同的chunk
,加快首次加载的速度。
React和Vue都提供了异步加载组件的方式,异步加载的组件不会阻塞主页面的渲染,首屏加载速度更快,所以我们可以考虑将一些次要的、较为复杂的组件通过异步的方式引入,实现'dynamic import'。
React懒加载
React可以使用React.lazy()
实现懒加载:
const Chart = React.lazy(() => {
import("./Chart");// Webpack打包之后的chunk名字就是Chart
})
Vue懒加载
Vue实现懒加载有两种方式:一是异步组件声明,二是通过路由懒加载。
异步组件声明
Vue.component('chart', () => import('./chart'));
路由懒加载
const chart = () => import('./chart');
// 路由引入
const routes = [
{
name: "Chart",
path: 'chart',
component: chart
}
]
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!