纪录一下自己的webpack优化的一点笔记
开发优化(dllplugin)
dllplugin也叫预打包,当插件安装多了以后,webpack每次运行/热更新都会很慢,所以需要我们做一次预打包,尤其是对于一些庞大的老vue2项目更是非做不可了,具体的配置流程如下
1.最外层目录新建dll.js,在这里定义需要预打包的包
const path = require('path')
const DllPlugin = require('webpack/lib/DllPlugin')
//const { srcPath, distPath } = require('@/utils/paths')
const dllPath = 'public/vendor'
module.exports = {
mode: 'development',
// JS 执行入口文件
entry: {
// 把 React 相关模块的放到一个单独的动态链接库
// dllplugin预打包element有问题
// vue 打包进去也会有问题
vue: [
'vue-router',
'echarts',
'vue',
'vuex',
'wangeditor',
'axios',
'lodash',
'echarts-gl',
'uuid'
]
},
output: {
// 输出的动态链接库的文件名称,[name] 代表当前动态链接库的名称,
// 也就是 entry 中配置的 react 和 polyfill
filename: '[name].dll.js',
// 输出的文件都放到 dist 目录下
path: path.join(__dirname, dllPath),
// 存放动态链接库的全局变量名称,例如对应 react 来说就是 _dll_react
// 之所以在前面加上 _dll_ 是为了防止全局变量冲突
library: '_dll_[name]'
},
plugins: [
// 接入 DllPlugin
new DllPlugin({
// 动态链接库的全局变量名称,需要和 output.library 中保持一致
// 该字段的值也就是输出的 manifest.json 文件 中 name 字段的值
// 例如 react.manifest.json 中就有 "name": "_dll_react"
name: '_dll_[name]',
// 描述动态链接库的 manifest.json 文件输出时的文件名称
path: path.join(path.join(__dirname, dllPath), '[name].manifest.json')
})
]
}
接着在vue.config.js中配置预打包命令
// dll动态链
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin')
config.plugins.push(
new DllReferencePlugin({
// context: __dirname,
// manifest就是我们第3步中打包出来的json文件
// manifest: require('./vendor-manifest.json'),
manifest: require('./public/vendor/vue.manifest.json')
})
)
接着在入门文件index.html引入已经预打包好的包
<script src="./vendor/vue.dll.js"></script>
这里是我的文件路径,大家可以参考
生产优化 cdn,入口index.html引入常用包cdn服务器地址,优化产出包大小
const cdn = {
css: ['https://unpkg.com/element-ui/lib/theme-chalk/index.css'],
js: [
'https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js',
'https://unpkg.com/element-ui/lib/index.js'
]
}
config.externals = {
// <script></script>标签会生成一个全局属性
vue: 'Vue',
'element-ui': 'ELEMENT'
// vuex: 'Vuex',
// 'vue-router': 'VueRouter',
// axios: 'axios'
}
}
if (isProd) {
//生产环境注入cdn
config.plugin('html').tap((args) => {
args[0].cdn = cdn
return args
})
}
在入门index.html文件引入
<title><%= htmlWebpackPlugin.options.title %></title>
<!-- 使用CDN的CSS文件 -->
<% for (var i in htmlWebpackPlugin.options.cdn &&
htmlWebpackPlugin.options.cdn.css) { %>
<!-- <link
href="<%= htmlWebpackPlugin.options.cdn.css[i] %>"
rel="preload"
as="style"
/> -->
<link
href="<%= htmlWebpackPlugin.options.cdn.css[i] %>"
rel="stylesheet"
/>
<% } %>
<!-- 使用CDN的JS文件 -->
</head>
<body>
<noscript>
<strong>
We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
properly without JavaScript enabled. Please enable it to continue.
</strong>
</noscript>
<div id="app"></div>
<% for (var i in htmlWebpackPlugin.options.cdn &&
htmlWebpackPlugin.options.cdn.js) { %> -->
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
生产优化其余的办法
// 修改抽离css插件
config.plugin('extract-css').tap(() => [
{
filename: 'css/[name].[contenthash:8].${timeStamp}.css',
chunkFilename: 'css/[name].[contenthash:8].${timeStamp}.css'
}
])
// 对异步同步代码都做处理
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 // 公共模块最少复用过几次
}
}
})
补充一点,对于刚打包出来文件需要用户手动清理缓存这个问题如何解决?
// 输出重构 打包编译后的js文件名称,添加时间戳
config.output.filename(`js/js[name].${timeStamp}.js`)
config.output.chunkFilename(`js/chunk.[id].${timeStamp}.js`)
在入口文件上添加 no store/cache,强行不走缓存
切割js代码优化
config.optimization.splitChunks({
chunks: "all",
cacheGroups: {
libs: {
name: "chunk-libs",
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: "initial", // only package third parties that are initially dependent
},
elementUI: {
name: "chunk-elementUI", // split elementUI into a single package
priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm
},
commons: {
name: "chunk-commons",
test: resolve("src/components"), // can customize your rules
minChunks: 3, // minimum common number
priority: 5,
reuseExistingChunk: true,
},
},
});