前言
本文是自己在實際項目中總結的幾點較爲實用的Vue的性能優化,希望能對大家實際項目以及面試產生幫助。
一、gzip壓縮
gizp壓縮是一種http請求優化方式,通過減少文件體積來提高加載速度。html、js、css文件甚至json數據都可以用它壓縮,可以減小60%以上的體積。(需要後端支持)
1. 安裝npm i compression-webpack-plugin -D
2. vue.config.js文件裏配置
// 導包
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 // 是否刪除原文件
})
]
}
}
}
}
3.運行npm run build
gzip壓縮後,通過gzip壓縮可以使Vue首頁加載速度大大提升,以下是壓縮前與壓縮後
4.添加打包分析可以更具體的查看
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
5.參考資料:
二、路由懶加載(按需加載)
當打包構建應用時,JavaScript 包會變得非常大,影響頁面加載。如果我們能把不同路由對應的組件分割成不同的代碼塊,然後當路由被訪問的時候才加載對應組件,這樣就更加高效了。
1.在路由配置中import方法實現路由懶加載
代碼如下(示例):
const router = new VueRouter({
routes: [
{
path: '/foo', component: () => import('./Foo.vue') }
]
})
2.參考資料
二、第三方插件的按需引入(按需加載)
以Vant爲例,藉助 babel-plugin-import ,可以只引入需要的組件,以達到減少體積的目的
1.安裝插件
npm i babel-plugin-import -D
2.在.babelrc 中添加配置
// 在.babelrc 中添加配置
// 注意:webpack 1 無需設置 libraryDirectory
{
"plugins": [
["import", {
"libraryName": "vant",
"libraryDirectory": "es",
"style": true
}]
]
}
3.按需加載組件
// 接着你可以在代碼中直接引入 Vant 組件
// 插件會自動將代碼轉化爲方式二中的按需引入形式
import {
Button } from 'vant';
4.參考資料:
三、減少接口請求
1.每次路由跳轉或者反覆多次刷新時重新向服務器發送請求時取消上一次發送的接口請求
- 請求攔截器js文件中設置
// 取消請求
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)
}
2.keep-alive頁面緩存
當你希望某個頁面不被重新渲染,就可以使用Vue的keep-alive組件,不僅可以緩存當前頁面數據,還可以避免多次重複渲染降低性能。
- 在組件中給name
export default {
name: 'article',
// keep-alive的生命週期
// 初次進入時:created > mounted > activated
// 再次進入:只會觸發 activated
activated () {
// to do..
},
// 退出後觸發 deactivated
deactivated () {
// to do..
}
}
- 在路由出口處用keep-alive組件包裹住
<!-- 路由出口 -->
<!-- include - 字符串或正則表達式。只有名稱匹配的組件會被緩存。
exclude - 字符串或正則表達式。任何名稱匹配的組件都不會被緩存。
max - 數字。最多可以緩存多少組件實例。 -->
<keep-alive include="article">
<router-view></router-view>
</keep-alive>
- 參考資料
Vue官方文檔
3.防抖節流
1.防抖工具型方法封裝
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)
}
}
2.節流工具型方法封裝
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)
}
}
}
四、利用Object.freeze()實現vue長列表性能優化
vue利用Object.defineProperty中的setter和geeter來對數據對象進行劫持,來實現視圖響應數據的變化,然而有些時候我們的組件就是純粹的數據展示,不會有任何改變,我們就不需要 vue來劫持我們的數據,在大量數據展示的情況下,這能夠很明顯的減少組件初始化的時間,那如何禁止 vue劫持我們的數據呢?可以通過 object.freeze方法來凍結一個對象,一旦被凍結的對象就再也不能被修改了。
- Object.freeze()介紹
Object.freeze() 方法可以凍結一個對象。一個被凍結的對象再也不能被修改;凍結了一個對象則不能向這個對象添加新的屬性,不能刪除已有屬性,不能修改該對象已有屬性的可枚舉性、可配置性、可寫性,以及不能修改已有屬性的值。此外,凍結一個對象後該對象的原型也不能被修改。freeze() 返回和傳入的參數相同的對象。
總結
以上僅僅是Vue項目性能優化的一部分,以後有時間還會給大家繼續更新,感謝!!!