在使用elementUI構建公司管理系統時,發現首屏加載時間長,加載的網絡資源比較多,對系統的體驗性會差一點,而且用webpack打包的vuejs的vendor包會比較大。所以通過搜集網上所有對於vuejs項目的性能優化,做了有關3方面的優化建議,主要包括:上線代碼包打包、源碼編寫優化、用戶體驗優化。(下面的優化建議只在vue-cli腳手架下做過測試,詳情請參考)
1.代碼包優化
- 屏蔽sourceMap
- 待下項目開發完成。進行打包源碼上線環節,需要對項目開發環節的開發提示信息以及錯誤信息進行屏蔽,一方面可以減少上線代碼包的大小;另一方面提高系統的安全性。在vuejs項目的config目錄下有三個文件dev.env.js(開發環境配置文件)、prod.env.js(上線配置文件)、index.js(通用配置文件)。vue-cli腳手架在上線配置文件會自動設置允許sourceMap打包,所以在上線前可以屏蔽sourceMap。如下所示,index.js的配置如下,通用配置文件分別對開發環境和上線環境做了打包配置分類,在build對象中的配置信息中,productionSourceMap修改成false:
-
-
// Template version: 1.3.1
-
// see http://vuejs-templates.github.io/webpack for documentation.
-
-
const path = require('path')
-
-
module.exports = {
-
dev: {
-
-
// Paths
-
assetsSubDirectory: 'static',
-
assetsPublicPath: '/',
-
proxyTable: {},
-
-
// Various Dev Server settings
-
host: 'localhost', // can be overwritten by process.env.HOST
-
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
-
autoOpenBrowser: false,
-
errorOverlay: true,
-
notifyOnErrors: true,
-
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
-
-
-
/**
-
* Source Maps
-
*/
-
-
// https://webpack.js.org/configuration/devtool/#development
-
devtool: 'cheap-module-eval-source-map',
-
-
// If you have problems debugging vue-files in devtools,
-
// set this to false - it *may* help
-
// https://vue-loader.vuejs.org/en/options.html#cachebusting
-
cacheBusting: true,
-
-
cssSourceMap: true
-
},
-
-
build: {
-
// Template for index.html
-
index: path.resolve(__dirname, '../dist/ndindex.html'),
-
-
// Paths
-
assetsRoot: path.resolve(__dirname, '../dist'),
-
assetsSubDirectory: 'static',
-
assetsPublicPath: './',
-
-
/**
-
* Source Maps
-
*/
-
-
productionSourceMap: false,
-
// https://webpack.js.org/configuration/devtool/#production
-
devtool: '#source-map',
-
-
// Gzip off by default as many popular static hosts such as
-
// Surge or Netlify already gzip all static assets for you.
-
// Before setting to `true`, make sure to:
-
// npm install --save-dev compression-webpack-plugin
-
productionGzip: true,
-
productionGzipExtensions: ['js', 'css','svg'],
-
-
// Run the build command with an extra argument to
-
// View the bundle analyzer report after build finishes:
-
// `npm run build --report`
-
// Set to `true` or `false` to always turn it on or off
-
bundleAnalyzerReport: process.env.npm_config_report
-
}
-
}
- 對項目代碼中的JS/CSS/SVG(*.ico)文件進行gzip壓縮
- 在vue-cli腳手架的配置信息中,有對代碼進行壓縮的配置項,例如index.js的通用配置,productionGzip設置為true,但是首先需要對compress-webpack-plugin支持,所以需要通過 npm install --save-dev compression-webpack-plugin(如果npm install出錯了,就使用cnpm install安裝。可能網絡比較差npm install會出現頻率比較大),gzip會對js、css文件進行壓縮處理;對於圖片進行壓縮問題,對於png,jpg,jpeg沒有壓縮效果,對於svg,ico文件以及bmp文件壓縮效果達到50%,在productionGzipExtensions: ['js', 'css','svg']設置需要進行壓縮的什么格式的文件。對項目文件進行壓縮之后,需要瀏覽器客戶端支持gzip以及后端支持gzip。下面可以查看成功支持gzip狀態:
-
-
// Template version: 1.3.1
-
// see http://vuejs-templates.github.io/webpack for documentation.
-
const path = require('path')
-
module.exports = {
-
build: {
-
// Template for index.html
-
index: path.resolve(__dirname, '../dist/ndindex.html'),
-
-
// Paths
-
assetsRoot: path.resolve(__dirname, '../dist'),
-
assetsSubDirectory: 'static',
-
assetsPublicPath: './',
-
-
/**
-
* Source Maps
-
*/
-
-
productionSourceMap: false,
-
// https://webpack.js.org/configuration/devtool/#production
-
devtool: '#source-map',
-
-
// Gzip off by default as many popular static hosts such as
-
// Surge or Netlify already gzip all static assets for you.
-
// Before setting to `true`, make sure to:
-
// npm install --save-dev compression-webpack-plugin
-
productionGzip: true,
-
productionGzipExtensions: ['js', 'css','svg'],
-
-
// Run the build command with an extra argument to
-
// View the bundle analyzer report after build finishes:
-
// `npm run build --report`
-
// Set to `true` or `false` to always turn it on or off
-
bundleAnalyzerReport: process.env.npm_config_report
-
}
-
}
-
ResponseHeader- content-encoding:"gzip"
- 對路由組件進行懶加載
- 在路由配置文件里,這里是router.js里面引用組件。如果使用同步的方式加載組件,在首屏加載時會對網絡資源加載加載比較多,資源比較大,加載速度比較慢。所以設置路由懶加載,按需加載會加速首屏渲染。在沒有對路由進行懶加載時,在Chrome里devtool查閱可以看到首屏網絡資源加載情況(6requests 3.8MB transfferred Finish:4.67s DOMContentLoaded 2.61s Load 2.70s)。在對路由進行懶加載之后(7requests 800kb transffered Finish2.67s DOMContentLoaded 1.72s Load 800ms),可以看見加載速度明顯加快。但是進行懶加載之后,實現按需加載,那么項目打包不會把所有js打包進app.[hash].js里面,優點是可以減少app.[hash].js體積,缺點就是會把其它js分開打包,造成多個js文件,會有多次https請求。如果項目比較大,需要注意懶加載的效果。
-
// 實現懶加載方式
-
import Vue from "vue";
-
import Router from "vue-router";
-
Vue.use(Router);
-
export default new Router({
-
mode: "history",
-
base: "/facex/district/",
-
routes: [
-
{ path: "/", redirect: "index" },
-
{
-
path: "/",
-
name: "home",
-
component: resolve=>require(["@/views/home"],resolve),
-
children: [
-
{
-
// 員工查詢
-
path: "/employees",
-
component: resolve=>require(["@/components/employees"],resolve)
-
},
-
{
-
// 首頁
-
path: "/index",
-
component: resolve=>require(["@/views/index"],resolve)
-
},
-
{
-
// 訪客查詢
-
path: "/visitorlist",
-
component: resolve=>require(["@/components/visitorlist"],resolve)
-
},
-
{
-
path: "/department",
-
component: resolve=>require(["@/views/department"],resolve)
-
},
-
//識別查詢
-
{
-
path: "/discriminate",
-
component: resolve=>require(["@/components/discriminate"],resolve)
-
},
-
{
-
path: "/addDevice",
-
component: resolve=>require(["@/views/addDevice"],resolve)
-
},
-
{
-
path: "/districtNotice",
-
component: resolve=>require(["@/components/districtNotice"],resolve)
-
}
-
]
-
},
-
{
-
path: "/noticeList",
-
name: "noticeList",
-
component: resolve=>require(["@/views/noticeList"],resolve)
-
},
-
{
-
path: "/login",
-
name: "login",
-
component: resolve=>require(["@/views/login"],resolve)
-
},
-
{
-
path: "/register",
-
name: "register",
-
component: resolve=>require(["@/views/register"],resolve)
-
},
-
{
-
path: "/setaccount",
-
name: "setaccount",
-
component:resolve=>require(["@/views/setaccount"],resolve)
-
},
-
{
-
path: "/addGroup",
-
name: "addGroup",
-
component:resolve=>require(["@/views/addGroup"],resolve)
-
},
-
{
-
path: "/guide",
-
name: "guide",
-
component:resolve=>require(["@/components/guide"],resolve)
-
},
-
{
-
path: "/addNotice",
-
name: "addNotice",
-
component: resolve=>require(["@/views/addNotice"],resolve)
-
}
-
]
-
});i
2.源碼優化
- v-if 和 v-show選擇調用
- v-show和v-if的區別是:v-if是懶加載,當狀態為true時才會加載,並且為false時不會占用布局空間;v-show是無論狀態是true或者是false,都會進行渲染,並對布局占據空間對於在項目中,需要頻繁調用,不需要權限的顯示隱藏,可以選擇使用v-show,可以減少系統的切換開銷。
- 為item設置唯一key值,
- 在列表數據進行遍歷渲染時,需要為每一項item設置唯一key值,方便vuejs內部機制精准找到該條列表數據。當state更新時,新的狀態值和舊的狀態值對比,較快地定位到diff。
- 細分vuejs組件
- 在項目開發過程之中,第一版本把所有的組件的布局寫在一個組件中,當數據變更時,由於組件代碼比較龐大,vuejs的數據驅動視圖更新比較慢,造成渲染比較慢。造成比較差的體驗效果。所以把組件細分,比如一個組件,可以把整個組件細分成輪播組件、列表組件、分頁組件等。
- 減少watch的數據
- 當組件某個數據變更后需要對應的state進行變更,就需要對另外的組件進行state進行變更。可以使用watch監聽相應的數據變更並綁定事件。當watch的數據比較小,性能消耗不明顯。當數據變大,系統會出現卡頓,所以減少watch的數據。其它不同的組件的state雙向綁定,可以采用事件中央總線或者vuex進行數據的變更操作。
- 內容類系統的圖片資源按需加載
- 對於內容類系統的圖片按需加載,如果出現圖片加載比較多,可以先使用v-lazy之類的懶加載庫或者綁定鼠標的scroll事件,滾動到可視區域先再對數據進行加載顯示,減少系統加載的數據。
- SSR(服務端渲染)
- 如果項目比較大,首屏無論怎么做優化,都出現閃屏或者一陣黑屏的情況。可以考慮使用SSR(服務端渲染),vuejs官方文檔提供next.js很好的服務端解決方案,但是局限性就是目前僅支持Koa、express等Nodejs的后台框架,需要webpack支持。目前自己了解的就是后端支持方面,vuejs的后端渲染支持php,其它的不太清楚。
3.用戶體驗優化
- better-click防止iphone點擊延遲
- 在開發移動端vuejs項目時,手指觸摸時會出現300ms的延遲效果,可以采用better-click對ipone系列的兼容體驗優化。
- 菊花loading
- 菊花loading,在加載資源過程之中,可以提供loading。此菊花loading不是那菊花。所以可以自由選擇自己喜歡的菊花。
- 骨架屏加載
-
在首屏加載資源較多,可能會出現白屏和閃屏的情況。體驗不好。盜圖一波,小米商城使用骨架屏進行首屏在資源數據還沒有加載完成時顯示,給很好的體驗效果。
-