本文是自己在实际项目中总结的几点较为实用的Vue的性能优化,希望能对大家实际项目以及面试产生帮助。
gizp压缩是一种http请求优化方式,通过减少文件体积来提高加载速度。html、js、css文件甚至json数据都可以用它压缩,可以减小60%以上的体积。(需要后端支持)
npm i compression-webpack-plugin -D
// 导包
const CompressionWebpackPlugin = require('compression-webpack-plugin')
// 匹配文件名
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i
// 配置
module.exports = {
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
return {
plugins: [
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip', // 默认为gzip
test: productionGzipExtensions,
threshold: 2048, // 对超过2k的数据进行压缩
minRatio: 0.8, // 仅压缩比该比率更好的(minRatio = Compressed Size / Original Size)
deleteOriginalAssets: false // 是否删除原文件
})
]
}
}
}
}
npm run build
gzip压缩后,通过gzip压缩可以使Vue首页加载速度大大提升,以下是压缩前与压缩后
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
module.exports = {
// 构建体积分析
chainWebpack: config => {
config
.plugin('webpack-bundle-analyzer')
.use(BundleAnalyzerPlugin)
.init(Plugin => new Plugin())
}
}
执行npm run build --report
CompressionWebpack插件
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
代码如下(示例):
const router = new VueRouter({
routes: [
{
path: '/foo', component: () => import('./Foo.vue') }
]
})
vue官方文档路由懒加载
以Vant为例,借助 babel-plugin-import ,可以只引入需要的组件,以达到减少体积的目的
npm i babel-plugin-import -D
// 在.babelrc 中添加配置
// 注意:webpack 1 无需设置 libraryDirectory
{
"plugins": [
["import", {
"libraryName": "vant",
"libraryDirectory": "es",
"style": true
}]
]
}
// 接着你可以在代码中直接引入 Vant 组件
// 插件会自动将代码转化为方式二中的按需引入形式
import {
Button } from 'vant';
Vant自动按需引入组件
// 取消请求
let cancelArr = []
window.cancelAxios = function (url, allAxios = false) {
cancelArr = cancelArr.filter(item => {
if (allAxios) {
item.c()
return false
} else {
if (item.url === url) {
item.c()
return false
} else {
return true
}
}
})
}
// 请求拦截器
_fetch.interceptors.request.use(
function (config) {
window.cancelAxios(config.url)
config.cancelToken = new axios.CancelToken(cancel => {
cancelArr.push({
url: config.url,
c: cancel
})
})
return config
},
function (error) {
return Promise.reject(error)
}
)
// 前置守卫
router.beforeEach((to, from, next) => {
// 每次跳转路由取消所有请求
window.cancelAxios('', true)
}
当你希望某个页面不被重新渲染,就可以使用Vue的keep-alive组件,不仅可以缓存当前页面数据,还可以避免多次重复渲染降低性能。
export default {
name: 'article',
// keep-alive的生命周期
// 初次进入时:created > mounted > activated
// 再次进入:只会触发 activated
activated () {
// to do..
},
// 退出后触发 deactivated
deactivated () {
// to do..
}
}
<!-- 路由出口 -->
<!-- include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max - 数字。最多可以缓存多少组件实例。 -->
<keep-alive include="article">
<router-view></router-view>
</keep-alive>
function debounce (fnEvent, time) {
var _time = null
return function () {
let _arg = arguments
let _this = this
if (_time) {
clearTimeout(_time)
}
_time = setTimeout(() => {
fnEvent.apply(_this, _arg)
}, time)
}
}
function throttle (fnEvent, time) {
var isLoading = false
return function () {
let _arg = arguments
if (!isLoading) {
isLoading = true
let _this = this
setTimeout(() => {
fnEvent.apply(_this, _arg)
isLoading = false
}, time)
}
}
}
vue利用Object.defineProperty中的setter和geeter来对数据对象进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要 vue来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,那如何禁止 vue劫持我们的数据呢?可以通过 object.freeze方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。
以上仅仅是Vue项目性能优化的一部分,以后有时间还会给大家继续更新,感谢!!!