所谓的性能优化在我看来就是访问速度的一个提升,那如何提升呢?下面是我的一些粗鄙的见解,请参考:
用过vue 的开发者应该都晓得开发vue 项目随着项目开发愈久用到的插件越来越多的情况下打包后的chunk-vendors.js
文件会越来越大,这个是最常见的导致页面加载缓慢文件之一:
推荐两款常见的比较好用的分析工具:
1、vue ui(可参考此博客vue ui 如何操作的)
2、webpack-bundle-analyzer打包文件分析工具webpack-bundle-analyzer
chunk-vendor.js文件说明: 来自第三方插件,也就是node_modules/ 下所有用到的依赖包集合的打包文件的输出。
下面是个人项目vue,config.js部分配置文件供参考:有更好建议请留言赐教
分包方式优化chunk-vendors.js 过大问题
const { defineConfig } = require('@vue/cli-service');
const path = require('path');
// const useCDNs = require('./useCDNs');
const webpack = require('webpack');
const CompressionPlugin = require('compression-webpack-plugin');
// const zlib = require('zlib');
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = defineConfig({
transpileDependencies: true,
productionSourceMap: false,
});
module.exports = {
// productionSourceMap: false,
publicPath: '/',
parallel: false,
pwa: { // pwa 缓存处理
iconPaths: {
favicon32: 'favicon.ico',
favicon16: 'favicon.ico',
appleTouchIcon: 'favicon.ico',
maskIcon: 'favicon.ico',
msTileImage: 'favicon.ico',
},
},
// 不输出 map 文件,以加速生产环境构建
chainWebpack: (config) => {
config.module
.rule('md')
.test(/\.md/)
.use('vue-loader')
.loader('vue-loader')
.end()
.use('vue-markdown-loader')
.loader('vue-markdown-loader/lib/markdown-compiler')
.options({
raw: true,
});
config.module.rule('svg').exclude.add(resolve('src/icons')).end();
config.module
.rule('icons')
.test(/\.svg$/)
.include.add(resolve('src/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]',
})
.end();
},
configureWebpack: {
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@i': path.resolve(__dirname, './src/assets'),
},
},
plugins: [
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /ElementPlus$/,
}),
new CompressionPlugin({ // 开启gzip压缩
filename: '[path][base].gz',
algorithm: 'gzip',
test: /\.ts$|\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8,
}),
],
// 开启分离 js
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
// maxInitialRequests: Infinity,
// minSize: 20000,
cacheGroups: {
commons: {
// split async commons chunk
name: 'chunk-async-commons',
minChunks: 2,
priority: 40,
chunks: 'async',
},
elementPlus: {
name: 'chunk-elementPlus', // split elementUI into a single package
priority: 30, // the weight needs to be larger than libs and app or it will be packaged into libs or app
test: /[\\/]node_modules[\\/]_?element-plus(.*)/, // in order to adapt to cnpm
},
},
},
},
},
devServer: {
//开发服务的一些处理
},
};
依赖包通过cdn方式引入来优化项目打包过大问题:
弊端: cdn外链资源请求慢的情况下,或者cdn当掉的话,那么项目启动肯定是会直接当掉或者一直加载中
/** @file useCDNs.js */
/** @typedef {string} ModuleName 模块名 */
/** @typedef {string} ModuleRefer 模块在全局的引用 */
/** @typedef {string} ElementTem 元素模板 */
/** @typedef {{mod:ModuleName;refer:ModuleRefer;el:ElementTem}} CDNItem cdn 项目 */
/**
* cdn 使用函数。
*
* 此函数可以在指定开发环境中,指定某些模块作为外部依赖出现,并把准备好的第三方 cdn 模板以 `cdns` 参数通过 HtmlWebpackPlugin 插件插入到 `public/index.html` 文件中。
* 你可以在 `public/index.html` 中使用 ejs 语法 <%= htmlWebpackPlugin.options.cdns %> 来插入准备好的 cdn。
*
* @param {import('webpack-chain')} config webpack-chain 实例
* @param {CDNItem[]} cdns 传入需要使用的 cdn 数组
* @param {string} env 什么环境下使用 cdn ,默认生产环境
*/
module.exports = function useCDNs(config, cdns = [], env = 'production') {
if (process.env.NODE_ENV !== env) return;
config.externals(
cdns.reduce((prev, v) => {
prev[v.mod] = v.refer;
return prev;
}, {})
);
config.plugin('html').tap((args) => {
args[0].cdns = cdns.map((v) => v.el).join('');
return args;
});
};
在vue.config.js 中使用useCDNs.js将需要用的cdn资源注入
下面使用elemet-ui为例子:线上环境使用cdn方式,开发环境使用依赖方式、样式文件可以通过
在main.js/main.ts 中引入
const { defineConfig } = require('@vue/cli-service');
const path = require('path');
// const useCDNs = require('./useCDNs');
const webpack = require('webpack');
const CompressionPlugin = require('compression-webpack-plugin');
// const zlib = require('zlib');
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = defineConfig({
transpileDependencies: true,
productionSourceMap: false,
});
module.exports = {
// productionSourceMap: false,
publicPath: '/',
parallel: false,
pwa: {
iconPaths: {
favicon32: 'favicon.ico',
favicon16: 'favicon.ico',
appleTouchIcon: 'favicon.ico',
maskIcon: 'favicon.ico',
msTileImage: 'favicon.ico',
},
},
// 不输出 map 文件,以加速生产环境构建
chainWebpack: (config) => {
// 只在生产环境使用 cdn
useCDNs(config, {
mod: 'moment',
refer: 'moment',
el: 'https://cdn.jsdelivr.net/npm/[email protected]/moment.min.js',
});
configureWebpack: {
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@i': path.resolve(__dirname, './src/assets'),
},
},
plugins: [
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /ElementPlus$/,
}),
new CompressionPlugin({
filename: '[path][base].gz',
algorithm: 'gzip',
test: /\.ts$|\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8,
}),
],
// 开启分离 js
optimization: { // 如果打包出的chunk-vender文件过大的话使用它
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
// maxInitialRequests: Infinity,
// minSize: 20000,
cacheGroups: {
commons: {
// split async commons chunk
name: 'chunk-async-commons',
minChunks: 2,
priority: 40,
chunks: 'async',
},
elementPlus: {
name: 'chunk-elementPlus', // split elementUI into a single package
priority: 30, // the weight needs to be larger than libs and app or it will be packaged into libs or app
test: /[\\/]node_modules[\\/]_?element-plus(.*)/, // in order to adapt to cnpm
},
},
},
},
},
devServer: {
},
};
简单记录有问题可私信解决