本文具体介绍 vue.config.js 配置,以优化打包后 chunk-vendors.js 的大小,不具体介绍代码优化及各类api封装等。
1. 老生常谈的代码层面的优化
- 按需引入各类组件库
详情请见element 官网
1)element,echarts等
// element
import { Button, Input } from 'element-ui';
Vue.use(Button).use(Input);
// echarts
//引入基本模板
let echarts = require('echarts/lib/echarts')
// 引入折线图等组件
require('echarts/lib/chart/gauge')
require('echarts/lib/chart/radar')
Vue.prototype.$echarts = echarts
.babel.config.js
module.exports = {
presets: [["@vue/app", { useBuiltIns: "entry" }]],
plugins: [
// element官方教程
[
"component",
{
libraryName: "element-ui",
styleLibraryName: "theme-chalk"
}
]
]
}
-
v-if 和 v-show选择调用
1)少使用v-if
2)绑定key -
细分vuejs组件
1)组件细分,比如一个组件,可以把整个组件细分成轮播组件、列表组件、分页组件等。 -
减少watch的数据
1)数据大时,系统会出现卡顿,所以减少watch的数据。 -
路由懒加载
1)分割路由,当路由被访问的时候才加载对应的组件。
const router = new VueRouter({
routes: [
{ path: '/foo', component: () => import('./Foo.vue')}
]
})
- 内容类系统的图片资源按需加载
1)图片加载比较多,使用v-lazy之类的懒加载。
npm install vue-lazyload --save-dev
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload)
<img v-lazy="/static/img/1.png">
-
手动清除各类事件监听器,定时器及闭包等
-
SSR(服务端渲染)
如果项目比较大,首屏无论怎么做优化,都出现闪屏或者一阵黑屏的情况。可以考虑使用SSR(服务端渲染)
2. webpack 打包的优化
查看各类占比 npm run build --report
在 dist 文件里,report.html 在浏览器打开即可
- 开启gzip压缩
// 下载
npm install compression-webpack-plugin --save-dev
const isProduction = ["production", "prod"].includes(process.env.NODE_ENV);
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;
configureWebpack: config => {
const plugins = [];
if (isProduction) {
plugins.push(
new CompressionWebpackPlugin({
filename: "[path].gz[query]",
algorithm: "gzip",
test: productionGzipExtensions,
threshold: 10240,
minRatio: 0.8
})
);
}
config.plugins = [...config.plugins, ...plugins];
}
- splitChunks 单独打包第三方模块
// webpack配置
chainWebpack: (config) => {
if (isProduction) {
config.optimization.delete("splitChunks");
}
return config;
},
configureWebpack: config => {
if (isProduction) {
// 利用 splitChunks 单独打包第三方模块
config.optimization = {
splitChunks: {
cacheGroups: {
common: {
name: "chunk-common",
chunks: "initial",
minChunks: 2,
maxInitialRequests: 5,
minSize: 0,
priority: 1,
reuseExistingChunk: true,
enforce: true
},
vendors: {
name: "chunk-vendors",
test: /[\\/]node_modules[\\/]/,
chunks: "initial",
priority: 2,
reuseExistingChunk: true,
enforce: true
},
elementUI: {
name: "chunk-elementui",
test: /[\\/]node_modules[\\/]element-ui[\\/]/,
chunks: "all",
priority: 3,
reuseExistingChunk: true,
enforce: true
},
echarts: {
name: "chunk-echarts",
test: /[\\/]node_modules[\\/](vue-)?echarts[\\/]/,
chunks: "all",
priority: 4,
reuseExistingChunk: true,
enforce: true
}
}
}
};
}
config.plugins = [...config.plugins, ...plugins];
}
- 去除consollog
configureWebpack: config => {
const plugins = [];
if (isProduction) {
// 去除consollog
plugins.push(
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false, // 打包报错可注掉
drop_console: true,
drop_debugger: false,
pure_funcs: ["console.log"] //移除console
},
},
sourceMap: false,
parallel: true,
})
);
}
config.plugins = [...config.plugins, ...plugins];
}
设置完后,打包后可以看到 .gz 结尾的文件,在http请求的Request Headers 中能看到 Accept-Encoding:gzip。
要使服务器返回.gz文件,还需要对服务器进行配置,根据Request Headers的Accept-Encoding标签进行鉴别,如果支持gzip就返回.gz文件。
完整vue.config.js
const path = require('path');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;
// 生产环境名称
const isProduction = ["production", "prod"].includes(process.env.NODE_ENV);
const resolve = dir => path.join(__dirname, dir);
module.exports = {
publicPath: '/', // 公共路径
runtimeCompiler: true, // 是否使用包含运行时编译器的 Vue 构建版本
outputDir: process.env.NODE_ENV === "development" ? 'devdist' : 'dist', // 不同的环境打不同包名
pluginOptions: {
"style-resources-loader": {
preProcessor: "less",
patterns: [
// 这个是加上自己的路径,
// 注意:试过不能使用别名路径
path.resolve(__dirname, "./src/assets/css/variable.less")
]
}
},
lintOnSave: false, // 关闭eslint
productionSourceMap: false, // 清楚 .map 文件
devServer: { // 配置服务器
port: 8111,
open: true,
https: false,
proxy: {
'/api/*': {
target: process.env.VUE_APP_URL, // 目标 API 地址
ws: true, // 是否代理 websockets
changOrigin: true, // 跨域配置
pathRewrite: {
'^/api': '/'
}
}
}
},
// webpack配置
chainWebpack: (config) => {
// 别名路径
config.resolve.alias
.set('@', resolve('src'))
.set('@i', resolve('src/assets/image'))
.set('@s', resolve('src/assets/css'))
.set('@j', resolve('src/assets/js'))
if (isProduction) {
config.optimization.delete("splitChunks");
}
return config;
},
// 配置webpack
configureWebpack: config => {
const plugins = [];
if (isProduction) {
// 开启gzip压缩
plugins.push(
new CompressionWebpackPlugin({
filename: "[path].gz[query]",
algorithm: "gzip",
test: productionGzipExtensions,
threshold: 10240,
minRatio: 0.8
})
);
// 利用 splitChunks 单独打包第三方模块
config.optimization = {
splitChunks: {
cacheGroups: {
common: {
name: "chunk-common",
chunks: "initial",
minChunks: 2,
maxInitialRequests: 5,
minSize: 0,
priority: 1,
reuseExistingChunk: true,
enforce: true
},
vendors: {
name: "chunk-vendors",
test: /[\\/]node_modules[\\/]/,
chunks: "initial",
priority: 2,
reuseExistingChunk: true,
enforce: true
},
elementUI: {
name: "chunk-elementui",
test: /[\\/]node_modules[\\/]element-ui[\\/]/,
chunks: "all",
priority: 3,
reuseExistingChunk: true,
enforce: true
},
echarts: {
name: "chunk-echarts",
test: /[\\/]node_modules[\\/](vue-)?echarts[\\/]/,
chunks: "all",
priority: 4,
reuseExistingChunk: true,
enforce: true
}
}
}
};
// 去除consollog
plugins.push(
new UglifyJsPlugin({
uglifyOptions: {
compress: {
// warnings: false,
drop_console: true,
drop_debugger: false,
pure_funcs: ["console.log"] //移除console
},
},
sourceMap: false,
parallel: true,
})
);
config.externals = {
}
}
config.plugins = [...config.plugins, ...plugins];
}
}
网友评论