开发过程中有时候遇到有公共的代码或者多次引用同一个第三方库,那么这个时候打包,就可能将公共代码或者第三方库进行多次打包,这个时候需要将这些代码抽离成一个单独文件,这样打包之后体积更小,有利于提高打包效率,同时也可以减少引用和加载的次数。
同时也可以避免因文件修改,导致第三方库也进行打包。比如不过不抽离第三方库,只要修改业务逻辑,就会导致hash值变化,从而进行打包,因第三方库也在文件中,那么第三方也进行打包,如果抽离出来,即使业务逻辑修改,导致打包,但是第三方库代码未变,从而第三方库也不打包。
项目目录
image.png
例如在other.js和index.js都引入了 math.js
image.png image.png那么打包之后对应的index和other都包含这段公共逻辑代码
image.png image.png在相对环境文件中配置如下:
webpack.prod.js
const webpack = require('webpack')
const { merge } = require('webpack-merge')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const TerserJSPlugin = require('terser-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const webpackCommonConf = require('./webpack.common.js')
const { srcPath, distPath } = require('./paths')
module.exports = merge(webpackCommonConf, {
mode: 'production',
output: {
// filename: 'bundle.[contenthash:8].js', // 打包代码时,加上 hash 戳
filename: '[name].[contenthash:8].js', // name 即多入口时 entry 的 key
path: distPath,
// publicPath: 'http://cdn.abc.com' // 修改所有静态文件 url 的前缀(如 cdn 域名),这里暂时用不到
},
module: {
rules: [
// 图片 - 考虑 base64 编码的情况
{
test: /\.(png|jpg|jpeg|gif)$/,
use: {
loader: 'url-loader',
options: {
// 小于 5kb 的图片用 base64 格式产出
// 否则,依然延用 file-loader 的形式,产出 url 格式
limit: 5 * 1024,
// 打包到 img 目录下
outputPath: '/img1/',
// 设置图片的 cdn 地址(也可以统一在外面的 output 中设置,那将作用于所有静态资源)
// publicPath: 'http://cdn.abc.com'
}
}
},
// 抽离 css
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, // 注意,这里不再用 style-loader
'css-loader',
'postcss-loader'
]
},
// 抽离 less
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader, // 注意,这里不再用 style-loader
'css-loader',
'less-loader',
'postcss-loader'
]
}
]
},
plugins: [
new CleanWebpackPlugin(), // 会默认清空 output.path 文件夹
new webpack.DefinePlugin({
// window.ENV = 'production'
ENV: JSON.stringify('production')
}),
// 抽离 css 文件
new MiniCssExtractPlugin({
filename: 'css/main.[contenthash:8].css'
})
],
optimization: {
// 压缩 css
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
// 分割代码块
splitChunks: {
chunks: 'all',
/**
* initial 入口chunk,对于异步导入的文件不处理
* 针对直接引入的代码
async 异步chunk,只对异步导入的文件处理
all 全部chunk 一般用这个
*/
// 缓存分组
cacheGroups: {
// 第三方模块
vendor: {
name: 'vendor', // chunk 名称 即打包后所有第三方库都叫vendor
// 拆分的时候 第三方和功能代码有可能冲突,比如第三方库也作为公共代码在多个地方引用
// 此时用priority 先按第三方模块进行抽离,未命中在按公共模块抽离
// priority越大 优先级越大
priority: 1, // 权限更高,优先抽离,重要!!!
// 通过test 来检测是否命中 通过检测路径
test: /node_modules/,
// 最小分组尺寸 小于此值不抽离 如果有些文件比较小 没有必要抽离
minSize: 0, // 大小限制
// 只要复用超过1次 就抽离
minChunks: 1 // 最少复用过几次
},
// 公共的模块
common: {
name: 'common', // chunk 名称
priority: 0, // 优先级
minSize: 0, // 公共模块的大小限制
// 只要复用超过2次 就抽离
minChunks: 2 // 公共模块最少复用过几次
}
}
}
}
})
则在webpack.common.js中配置页面所要引用的js
image.png
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { srcPath, distPath } = require('./paths')
module.exports = {
entry: {
index: path.join(srcPath, 'index.js'),
other: path.join(srcPath, 'other.js')
},
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader'],
include: srcPath,
exclude: /node_modules/
}
]
},
plugins: [
// new HtmlWebpackPlugin({
// template: path.join(srcPath, 'index.html'),
// filename: 'index.html'
// })
// 多入口 - 生成 index.html
new HtmlWebpackPlugin({
template: path.join(srcPath, 'index.html'),
filename: 'index.html',
// chunks 表示该页面要引用哪些 chunk (即上面的 index 和 other),默认全部引用
chunks: ['index', 'vendor', 'common'] // 要考虑代码分割
}),
// 多入口 - 生成 other.html 引用other.js 和common.js
new HtmlWebpackPlugin({
template: path.join(srcPath, 'other.html'),
filename: 'other.html',
chunks: ['other', 'common'] // 考虑代码分割
})
]
}
打包后的目录
image.png打包后的index.html所引用的js
image.png打包后other.html所引用的js
image.png
网友评论