最近公司有个项目,使用vue的管理系统,由于在main中引入了大量的三方库,导致首页加载异常缓慢,然后让我来优化一下,在网上也看了些其他朋友的文章,于是简单做了下配置,总结一下
1、vue.config.js是个对vue项目中,webpack的一个配置文件,项目运行和打包的时候,webpack会自动查询这个文件
注:因为webpack是应用node语法,因此文件中也因改使用
2、主要通过配置代理服务器,和打包代码压缩,图片压缩,公共代码抽离,配置cdn引用,减少请求数量,打包优化为了减少包的体积太大,首页加载缓慢,建议组件和插件按需引入,在要使用的组件内部引入,不要都在main.js文件中引用,否则首页加载的文件过多,等待时间长,不利于用户体验
3、不过需要注意打包的插件版本和webpack版本可能会出现冲突报错
// An highlighted block
在这里插入代码片
//安装的插件
/*
cnpm install image-webpack-loader --save-dev 图片压缩
cnpm install compression-webpack-plugin --save-dev gzip压缩
cnpm install uglifyjs-webpack-plugin --save-dev js压缩
cnpm install webpack-bundle-analyzer --save-dev 可视化分析图
*/
const path = require('path');
// gzip压缩
const CompressionPlugin = require('compression-webpack-plugin')
const cdn = {
// 忽略打包的第三方库
externals: {
vue: 'Vue',
vuex: 'Vuex',
'vue-router': 'VueRouter',
axios: 'axios',
},
// 通过cdn方式使用
js: [
'https://cdn.bootcss.com/vue/2.6.11/vue.runtime.min.js',
'https://cdn.bootcss.com/vue-router/3.1.2/vue-router.min.js',
'https://cdn.bootcss.com/vuex/3.1.2/vuex.min.js',
'https://cdn.bootcss.com/axios/0.19.2/axios.min.js',
'https://cdn.bootcss.com/moment.js/2.24.0/moment.min.js',
'https://cdn.bootcss.com/echarts/4.6.0/echarts.min.js',
],
css: [],
};
module.exports = {
publicPath: '/', // 基本访问路径
outputDir: 'dist', // 输出文件目录
assetsDir: 'static',
productionSourceMap: false, // 关闭生产环境的 source map
chainWebpack: (config) => {
//配置loader文件转换
//如果页面图片较多,发很多http请求,会降低页面性能。这个问题可以通过url-loader解决。url-loader会将引入的图片编码,生成dataURl并将其打包到文件中,最终只需要引入这个dataURL就能访问图片了。当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的还会使用file-loader进行copy
config.module
.rule('swf')
.test(/\.swf$/)
.use('url-loader')
.loader('url-loader')
.tap((options) => {
return {
limit: 10000,
};
});
//图片压缩
config.module
.rule('images')
.test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({
bypassOnDebug: true
})
.end()
// 添加别名
config.resolve.alias
.set('@', resolve('src'))
.set('assets', resolve('src/assets'))
.set('components', resolve('src/components'))
.set('router', resolve('src/router'))
.set('store', resolve('src/store'))
.set('views', resolve('src/views'));
config.plugin('copy').tap((args) => {
args[0][0].to = 'resource';
return args;
});
// 移除 prefetch 插件
config.plugins.delete('prefetch-index');
// 移除 preload 插件,避免加载多余的资源
config.plugins.delete('preload-index');
// 配置cdn引入
config.plugin('html').tap((args) => {
args[0].cdn = cdn;
return args;
});
},
// 这个值是一个对象,则会通过 webpack-merge 合并到最终的配置中。
configureWebpack: (config) => {
// 展示打包图形化信息
config.plugins.push(
new BundleAnalyzer()
)
// 忽略打包配置
config.externals = cdn.externals;
// 生产环境相关配置
if (isProduction) {
//js文件压缩,默认已配置,可以不用写
config.plugins.push(new UglifyJsPlugin({
uglifyOptions: {
output: { // 删除注释
comments: false
},
// 生产环境自动删除console
compress: {
// warnings: false, // 若打包错误,则注释这行
// 清除 debugger 语句
drop_debugger: true,
drop_console: true, // 清除console语句
pure_funcs: ['console.log']
}
},
sourceMap: false,
parallel: true
}))
//gzip压缩
const productionGzipExtensions = ['html', 'js', 'css'];
config.plugins.push(
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
threshold: 10240, // 只有大小大于该值的资源会被处理 10240
minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
deleteOriginalAssets: false, // 删除原文件
})
);
// 公共代码抽离
config.optimization = {
// 分割代码块
splitChunks: {
cacheGroups: {//缓存组
//公用模块抽离
common: {
chunks: 'all',//值为all,initial,async
minSize: 0, //大于0个字节
minChunks: 2, //抽离公共代码时,这个代码块最小被引用的次数
},
//第三方库抽离
vendor: {
priority: 1, //权重
test: /node_modules/,
chunks: 'all',
minSize: 0, //大于0个字节
minChunks: 2, //在分割之前,这个代码块最小应该被引用的次数
},
//样式抽离
styles: {
name: 'styles',
test: /\.(sa|sc|c)ss$/,
chunks: 'all',
enforce: true
},
runtimeChunk: {
name: 'manifest'
}
},
},
};
}
},
devServer: {
overlay: {
warnings: false,
errors: false,
},
open: true,
// host: 'localhost',
// host: '0.0.0.0',
// port: 8081,
//https: false,
hotOnly: true,
proxy: {
'/api': {
// 代理地址
target: process.env.VUE_APP_API,//代理的地址
changeOrigin: true, // 是否跨域,是否改变服务端收到的请求头的host
secure: false,
pathRewrite: {
// '^/api': '/api/ctrl', //测试环境
'/api': '', //需要rewrite重写的, //本地联调
},
},
},
},
css: {
extract: true,
sourceMap: false,
loaderOptions: {
sass: {
prependData: `@import "~@/assets/scss/variables.scss";`,
},
less: {
modifyVars: {
/* less 变量覆盖,用于自定义 ant design 主题 */
'primary-color': '#1890FF',
'link-color': '#1890FF',
'border-radius-base': '4px',
},
javascriptEnabled: true,
}
},
},
};
index.html页面引入cdn文件:
<body>
<div id="app"></div>
<% for (var i in htmlWebpackPlugin.options.cdn &&
htmlWebpackPlugin.options.cdn.js) { %>
<script
src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"
crossorigin="anonymous"
></script>
<% } %>
</body>
注意:需要把main.js和router文件中的vue导入和router导入注释掉,vue-router库卸载掉
如:
// import Vue from 'vue'
// import Router from 'vue-router'
import { constantRouterMap } from '@/config/router.config'
Vue.use(VueRouter) //注意这里是VueRouter不是Router,不然会报Router未定义的错,从cdn中得到的是VueRouter对象
export default new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
scrollBehavior: () => ({ y: 0 }),
routes: constantRouterMap
})