前言
Vue 框架通過(guò)數(shù)據(jù)雙向綁定和虛擬 DOM 技術(shù)腔长,幫我們處理了前端開(kāi)發(fā)中最臟最累的 DOM 操作部分炎功, 我們不再需要去考慮如何操作 DOM 以及如何最高效地操作 DOM辛块;但 Vue 項(xiàng)目中仍然存在項(xiàng)目首屏優(yōu)化郊霎、Webpack 編譯配置優(yōu)化等問(wèn)題姥饰,所以我們?nèi)匀恍枰リP(guān)注 Vue 項(xiàng)目性能方面的優(yōu)化,使項(xiàng)目具有更高效的性能鲤屡、更好的用戶(hù)體驗(yàn)损痰。
本文是作者通過(guò)實(shí)際項(xiàng)目的優(yōu)化實(shí)踐進(jìn)行總結(jié)而來(lái),希望讀者讀完本文酒来,有一定的啟發(fā)思考卢未,從而對(duì)自己的項(xiàng)目進(jìn)行優(yōu)化起到幫助。本文內(nèi)容分為以下三部分組成:
Vue 代碼層面的優(yōu)化堰汉;
webpack 配置層面的優(yōu)化辽社;
基礎(chǔ)的 Web 技術(shù)層面的優(yōu)化。
一翘鸭、代碼層面的優(yōu)化
1.1滴铅、v-if 和 v-show 區(qū)分使用場(chǎng)景
v-if是真正的條件渲染,因?yàn)樗鼤?huì)確保在切換過(guò)程中條件塊內(nèi)的事件監(jiān)聽(tīng)器和子組件適當(dāng)?shù)乇讳N(xiāo)毀和重建就乓;也是惰性的:如果在初始渲染時(shí)條件為假汉匙,則什么也不做——直到條件第一次變?yōu)檎鏁r(shí),才會(huì)開(kāi)始渲染條件塊生蚁。
v-show就簡(jiǎn)單得多噩翠, 不管初始條件是什么,元素總是會(huì)被渲染守伸,并且只是簡(jiǎn)單地基于 CSS 的 display 屬性進(jìn)行切換绎秒。
所以,v-if 適用于在運(yùn)行時(shí)很少改變條件尼摹,不需要頻繁切換條件的場(chǎng)景见芹;v-show 則適用于需要非常頻繁切換條件的場(chǎng)景。
1.2蠢涝、computed 和 watch ?區(qū)分使用場(chǎng)景
computed:是計(jì)算屬性玄呛,依賴(lài)其它屬性值,并且 computed 的值有緩存和二,只有它依賴(lài)的屬性值發(fā)生改變徘铝,下一次獲取 computed 的值時(shí)才會(huì)重新計(jì)算 computed ?的值;
watch:更多的是「觀察」的作用,類(lèi)似于某些數(shù)據(jù)的監(jiān)聽(tīng)回調(diào) 惕它,每當(dāng)監(jiān)聽(tīng)的數(shù)據(jù)變化時(shí)都會(huì)執(zhí)行回調(diào)進(jìn)行后續(xù)操作怕午;
運(yùn)用場(chǎng)景:
當(dāng)我們需要進(jìn)行數(shù)值計(jì)算,并且依賴(lài)于其它數(shù)據(jù)時(shí)淹魄,應(yīng)該使用 computed郁惜,因?yàn)榭梢岳?computed 的緩存特性,避免每次獲取值時(shí)甲锡,都要重新計(jì)算兆蕉;
當(dāng)我們需要在數(shù)據(jù)變化時(shí)執(zhí)行異步或開(kāi)銷(xiāo)較大的操作時(shí),應(yīng)該使用 watch缤沦,使用 watch 選項(xiàng)允許我們執(zhí)行異步操作 ( 訪(fǎng)問(wèn)一個(gè) API )虎韵,限制我們執(zhí)行該操作的頻率,并在我們得到最終結(jié)果前缸废,設(shè)置中間狀態(tài)包蓝。這些都是計(jì)算屬性無(wú)法做到的。
1.3呆奕、v-for 遍歷必須為 item 添加 key养晋,且避免同時(shí)使用 v-if
(1)v-for 遍歷必須為 item 添加 key
在列表數(shù)據(jù)進(jìn)行遍歷渲染時(shí)衬吆,需要為每一項(xiàng) item 設(shè)置唯一 key 值梁钾,方便 Vue.js 內(nèi)部機(jī)制精準(zhǔn)找到該條列表數(shù)據(jù)。當(dāng) state 更新時(shí)逊抡,新的狀態(tài)值和舊的狀態(tài)值對(duì)比姆泻,較快地定位到 diff 。
(2)v-for 遍歷避免同時(shí)使用 v-if
v-for 比 v-if 優(yōu)先級(jí)高冒嫡,如果每一次都需要遍歷整個(gè)數(shù)組拇勃,將會(huì)影響速度,尤其是當(dāng)之需要渲染很小一部分的時(shí)候孝凌,必要情況下應(yīng)該替換成 computed 屬性方咆。
推薦:
<ul>? <liv-for="user in activeUsers":key="user.id">? ? {{ user.name }}? </li></ul>computed: {activeUsers:function(){returnthis.users.filter(function(user){returnuser.isActive? ? })? }}
不推薦:
- ? ? {{ user.name }}
1.4、長(zhǎng)列表性能優(yōu)化
Vue 會(huì)通過(guò) Object.defineProperty 對(duì)數(shù)據(jù)進(jìn)行劫持蟀架,來(lái)實(shí)現(xiàn)視圖響應(yīng)數(shù)據(jù)的變化瓣赂,然而有些時(shí)候我們的組件就是純粹的數(shù)據(jù)展示,不會(huì)有任何改變片拍,我們就不需要 Vue 來(lái)劫持我們的數(shù)據(jù)煌集,在大量數(shù)據(jù)展示的情況下,這能夠很明顯的減少組件初始化的時(shí)間捌省,那如何禁止 Vue 劫持我們的數(shù)據(jù)呢苫纤?可以通過(guò) Object.freeze 方法來(lái)凍結(jié)一個(gè)對(duì)象,一旦被凍結(jié)的對(duì)象就再也不能被修改了。
exportdefault{data:()=>({users: {}? }),asynccreated() {constusers =awaitaxios.get("/api/users");this.users =Object.freeze(users);? }};
1.5卷拘、事件的銷(xiāo)毀
Vue 組件銷(xiāo)毀時(shí)喊废,會(huì)自動(dòng)清理它與其它實(shí)例的連接,解綁它的全部指令及事件監(jiān)聽(tīng)器栗弟,但是僅限于組件本身的事件操禀。如果在 js 內(nèi)使用 addEventListene 等方式是不會(huì)自動(dòng)銷(xiāo)毀的,我們需要在組件銷(xiāo)毀時(shí)手動(dòng)移除這些事件的監(jiān)聽(tīng)横腿,以免造成內(nèi)存泄露颓屑,如:
created() {addEventListener('click',this.click,false)},beforeDestroy() {removeEventListener('click',this.click,false)}
1.6、圖片資源懶加載
對(duì)于圖片過(guò)多的頁(yè)面耿焊,為了加速頁(yè)面加載速度揪惦,所以很多時(shí)候我們需要將頁(yè)面內(nèi)未出現(xiàn)在可視區(qū)域內(nèi)的圖片先不做加載, 等到滾動(dòng)到可視區(qū)域后再去加載罗侯。這樣對(duì)于頁(yè)面加載性能上會(huì)有很大的提升器腋,也提高了用戶(hù)體驗(yàn)。我們?cè)陧?xiàng)目中使用 Vue 的 vue-lazyload 插件:
(1)安裝插件
npminstallvue-lazyload--save-dev
(2)在入口文件 man.js 中引入并使用
importVueLazyloadfrom'vue-lazyload'
然后再 vue 中直接使用
Vue.use(VueLazyload)
或者添加自定義選項(xiàng)
Vue.use(VueLazyload, {preLoad:1.3,error:'dist/error.png',loading:'dist/loading.gif',attempt:1})
(3)在 vue 文件中將 img 標(biāo)簽的 src 屬性直接改為 v-lazy 钩杰,從而將圖片顯示方式更改為懶加載顯示:
以上為 vue-lazyload 插件的簡(jiǎn)單使用纫塌,如果要看插件的更多參數(shù)選項(xiàng),可以查看 vue-lazyload 的 github 地址讲弄。
1.7措左、路由懶加載
Vue ?是單頁(yè)面應(yīng)用,可能會(huì)有很多的路由引入 避除,這樣使用 webpcak 打包后的文件很大怎披,當(dāng)進(jìn)入首頁(yè)時(shí),加載的資源過(guò)多瓶摆,頁(yè)面會(huì)出現(xiàn)白屏的情況凉逛,不利于用戶(hù)體驗(yàn)。如果我們能把不同路由對(duì)應(yīng)的組件分割成不同的代碼塊群井,然后當(dāng)路由被訪(fǎng)問(wèn)的時(shí)候才加載對(duì)應(yīng)的組件状飞,這樣就更加高效了。這樣會(huì)大大提高首屏顯示的速度书斜,但是可能其他的頁(yè)面的速度就會(huì)降下來(lái)诬辈。
路由懶加載:
constFoo =()=>import('./Foo.vue')constrouter =newVueRouter({routes: [{path:'/foo',component: Foo }? ]})
1.8、第三方插件的按需引入
我們?cè)陧?xiàng)目中經(jīng)常會(huì)需要引入第三方插件菩佑,如果我們直接引入整個(gè)插件自晰,會(huì)導(dǎo)致項(xiàng)目的體積太大,我們可以借助?babel-plugin-component?稍坯,然后可以只引入需要的組件酬荞,以達(dá)到減小項(xiàng)目體積的目的搓劫。以下為項(xiàng)目中引入 element-ui 組件庫(kù)為例:
(1)首先,安裝?babel-plugin-component?:
npminstallbabel-plugin-component -D
(2)然后混巧,將 .babelrc 修改為:
{"presets": [["es2015", {"modules":false}]],"plugins": [? ? ["component",? ? ? {"libraryName":"element-ui","styleLibraryName":"theme-chalk"? ? ? }? ? ]? ]}
(3)在 main.js 中引入部分組件:
importVuefrom'vue';import{ Button, Select }from'element-ui'; Vue.use(Button) Vue.use(Select)
1.9枪向、優(yōu)化無(wú)限列表性能
如果你的應(yīng)用存在非常長(zhǎng)或者無(wú)限滾動(dòng)的列表,那么需要采用?窗口化?的技術(shù)來(lái)優(yōu)化性能咧党,只需要渲染少部分區(qū)域的內(nèi)容秘蛔,減少重新渲染組件和創(chuàng)建 dom 節(jié)點(diǎn)的時(shí)間。你可以參考以下開(kāi)源項(xiàng)目 vue-virtual-scroll-list 和 vue-virtual-scroller ?來(lái)優(yōu)化這種無(wú)限列表的場(chǎng)景的傍衡。
1.10深员、服務(wù)端渲染 SSR or 預(yù)渲染
服務(wù)端渲染是指 Vue 在客戶(hù)端將標(biāo)簽渲染成的整個(gè) html 片段的工作在服務(wù)端完成,服務(wù)端形成的 html 片段直接返回給客戶(hù)端這個(gè)過(guò)程就叫做服務(wù)端渲染蛙埂。
(1)服務(wù)端渲染的優(yōu)點(diǎn):
更好的 SEO:因?yàn)?SPA 頁(yè)面的內(nèi)容是通過(guò) Ajax 獲取倦畅,而搜索引擎爬取工具并不會(huì)等待 Ajax 異步完成后再抓取頁(yè)面內(nèi)容,所以在 SPA 中是抓取不到頁(yè)面通過(guò) Ajax 獲取到的內(nèi)容绣的;而 SSR 是直接由服務(wù)端返回已經(jīng)渲染好的頁(yè)面(數(shù)據(jù)已經(jīng)包含在頁(yè)面中)叠赐,所以搜索引擎爬取工具可以抓取渲染好的頁(yè)面;
更快的內(nèi)容到達(dá)時(shí)間(首屏加載更快):SPA 會(huì)等待所有 Vue 編譯后的 js 文件都下載完成后屡江,才開(kāi)始進(jìn)行頁(yè)面的渲染芭概,文件下載等需要一定的時(shí)間等,所以首屏渲染需要一定的時(shí)間惩嘉;SSR 直接由服務(wù)端渲染好頁(yè)面直接返回顯示罢洲,無(wú)需等待下載 js 文件及再去渲染等,所以 SSR 有更快的內(nèi)容到達(dá)時(shí)間宏怔;
(2)服務(wù)端渲染的缺點(diǎn):
更多的開(kāi)發(fā)條件限制:例如服務(wù)端渲染只支持 beforCreate 和 created 兩個(gè)鉤子函數(shù)奏路,這會(huì)導(dǎo)致一些外部擴(kuò)展庫(kù)需要特殊處理,才能在服務(wù)端渲染應(yīng)用程序中運(yùn)行臊诊;并且與可以部署在任何靜態(tài)文件服務(wù)器上的完全靜態(tài)單頁(yè)面應(yīng)用程序 SPA 不同,服務(wù)端渲染應(yīng)用程序斜脂,需要處于 Node.js server 運(yùn)行環(huán)境抓艳;
更多的服務(wù)器負(fù)載:在 Node.js 中渲染完整的應(yīng)用程序,顯然會(huì)比僅僅提供靜態(tài)文件的 server 更加大量占用CPU 資源帚戳,因此如果你預(yù)料在高流量環(huán)境下使用玷或,請(qǐng)準(zhǔn)備相應(yīng)的服務(wù)器負(fù)載,并明智地采用緩存策略片任。
如果你的項(xiàng)目的 SEO 和 首屏渲染是評(píng)價(jià)項(xiàng)目的關(guān)鍵指標(biāo)偏友,那么你的項(xiàng)目就需要服務(wù)端渲染來(lái)幫助你實(shí)現(xiàn)最佳的初始加載性能和 SEO,具體的 Vue SSR 如何實(shí)現(xiàn)对供,可以參考作者的另一篇文章《Vue SSR 踩坑之旅》位他。如果你的 Vue 項(xiàng)目只需改善少數(shù)營(yíng)銷(xiāo)頁(yè)面(例如 ?/氛濒, /about,?/contact?等)的 SEO鹅髓,那么你可能需要預(yù)渲染舞竿,在構(gòu)建時(shí) (build time) 簡(jiǎn)單地生成針對(duì)特定路由的靜態(tài) HTML 文件。優(yōu)點(diǎn)是設(shè)置預(yù)渲染更簡(jiǎn)單窿冯,并可以將你的前端作為一個(gè)完全靜態(tài)的站點(diǎn)骗奖,具體你可以使用 prerender-spa-plugin 就可以輕松地添加預(yù)渲染 。
二醒串、Webpack 層面的優(yōu)化
2.1、Webpack 對(duì)圖片進(jìn)行壓縮
在 vue 項(xiàng)目中除了可以在?webpack.base.conf.js?中 url-loader 中設(shè)置 limit 大小來(lái)對(duì)圖片處理芜赌,對(duì)小于 limit 的圖片轉(zhuǎn)化為 base64 格式,其余的不做操作椎木。所以對(duì)有些較大的圖片資源,在請(qǐng)求資源的時(shí)候博烂,加載會(huì)很慢香椎,我們可以用?image-webpack-loader來(lái)壓縮圖片:
(1)首先畜伐,安裝 image-webpack-loader ?:
npminstallimage-webpack-loader--save-dev
(2)然后,在 webpack.base.conf.js ?中進(jìn)行配置:
{test: /.(png|jpe?g|gif|svg)(?.*)?$/,? use:[? ? {loader:'url-loader',? ? options: {limit:10000,name: utils.assetsPath('img/[name].[hash:7].[ext]')? ? ? }? ? },? ? {loader:'image-webpack-loader',? ? ? options: {? ? ? ? bypassOnDebug: true,? ? ? }? ? }? ]}
2.2躺率、減少 ES6 轉(zhuǎn)為 ES5 的冗余代碼
Babel 插件會(huì)在將?ES6?代碼轉(zhuǎn)換成 ES5 代碼時(shí)會(huì)注入一些輔助函數(shù)玛界,例如下面的 ES6 代碼:
classHelloWebpackextendsComponent{...}
這段代碼再被轉(zhuǎn)換成能正常運(yùn)行的 ES5 代碼時(shí)需要以下兩個(gè)輔助函數(shù):
babel-runtime/helpers/createClass// 用于實(shí)現(xiàn) class 語(yǔ)法babel-runtime/helpers/inherits// 用于實(shí)現(xiàn) extends 語(yǔ)法
在默認(rèn)情況下悼吱, Babel 會(huì)在每個(gè)輸出文件中內(nèi)嵌這些依賴(lài)的輔助函數(shù)代碼,如果多個(gè)源代碼文件都依賴(lài)這些輔助函數(shù)笨枯,那么這些輔助函數(shù)的代碼將會(huì)出現(xiàn)很多次遇西,造成代碼冗余。為了不讓這些輔助函數(shù)的代碼重復(fù)出現(xiàn)洲敢,可以在依賴(lài)它們時(shí)通過(guò)?require('babel-runtime/helpers/createClass')?的方式導(dǎo)入茄蚯,這樣就能做到只讓它們出現(xiàn)一次睦优。babel-plugin-transform-runtime?插件就是用來(lái)實(shí)現(xiàn)這個(gè)作用的刨秆,將相關(guān)輔助函數(shù)進(jìn)行替換成導(dǎo)入語(yǔ)句忆畅,從而減小 babel 編譯出來(lái)的代碼的文件大小。
(1)首先缓醋,安裝?babel-plugin-transform-runtime?:
npminstallbabel-plugin-transform-runtime--save-dev
(2)然后绊诲,修改 .babelrc ?配置文件為:
"plugins": ["transform-runtime"]
如果要看插件的更多詳細(xì)內(nèi)容,可以查看babel-plugin-transform-runtime 的 詳細(xì)介紹抗俄。
2.3世舰、提取公共代碼
如果項(xiàng)目中沒(méi)有去將每個(gè)頁(yè)面的第三方庫(kù)和公共模塊提取出來(lái)跟压,則項(xiàng)目會(huì)存在以下問(wèn)題:
相同的資源被重復(fù)加載,浪費(fèi)用戶(hù)的流量和服務(wù)器的成本震蒋。
每個(gè)頁(yè)面需要加載的資源太大查剖,導(dǎo)致網(wǎng)頁(yè)首屏加載緩慢,影響用戶(hù)體驗(yàn)禾唁。
所以我們需要將多個(gè)頁(yè)面的公共代碼抽離成單獨(dú)的文件无切,來(lái)優(yōu)化以上問(wèn)題 。Webpack 內(nèi)置了專(zhuān)門(mén)用于提取多個(gè)Chunk 中的公共部分的插件 CommonsChunkPlugin哆键,我們?cè)陧?xiàng)目中 CommonsChunkPlugin 的配置如下:
// 所有在 package.json 里面依賴(lài)的包籍嘹,都會(huì)被打包進(jìn) vendor.js 這個(gè)文件中。newwebpack.optimize.CommonsChunkPlugin({name:'vendor',minChunks:function(module, count){return(module.resource &&/.js$/.test(module.resource) &&module.resource.indexOf(path.join(__dirname,'../node_modules')) ===0? ? );? }}),// 抽取出代碼模塊的映射關(guān)系newwebpack.optimize.CommonsChunkPlugin({name:'manifest',chunks: ['vendor']})
如果要看插件的更多詳細(xì)內(nèi)容泪掀,可以查看 CommonsChunkPlugin 的 詳細(xì)介紹颂碘。
2.4头岔、模板預(yù)編譯
當(dāng)使用 DOM 內(nèi)模板或 JavaScript 內(nèi)的字符串模板時(shí),模板會(huì)在運(yùn)行時(shí)被編譯為渲染函數(shù)靠抑。通常情況下這個(gè)過(guò)程已經(jīng)足夠快了适掰,但對(duì)性能敏感的應(yīng)用還是最好避免這種用法类浪。
預(yù)編譯模板最簡(jiǎn)單的方式就是使用單文件組件——相關(guān)的構(gòu)建設(shè)置會(huì)自動(dòng)把預(yù)編譯處理好,所以構(gòu)建好的代碼已經(jīng)包含了編譯出來(lái)的渲染函數(shù)而不是原始的模板字符串个曙。
如果你使用 webpack受楼,并且喜歡分離 JavaScript 和模板文件艳汽,你可以使用 vue-template-loader,它也可以在構(gòu)建過(guò)程中把模板文件轉(zhuǎn)換成為 JavaScript 渲染函數(shù)米绕。
2.5馋艺、提取組件的 CSS
當(dāng)使用單文件組件時(shí)捐祠,組件內(nèi)的 CSS 會(huì)以 style 標(biāo)簽的方式通過(guò) JavaScript 動(dòng)態(tài)注入。這有一些小小的運(yùn)行時(shí)開(kāi)銷(xiāo)窿给,如果你使用服務(wù)端渲染,這會(huì)導(dǎo)致一段 “無(wú)樣式內(nèi)容閃爍 (fouc) ” 禁荒。將所有組件的 CSS 提取到同一個(gè)文件可以避免這個(gè)問(wèn)題角撞,也會(huì)讓 CSS 更好地進(jìn)行壓縮和緩存靴寂。
查閱這個(gè)構(gòu)建工具各自的文檔來(lái)了解更多:
webpack + vue-loader ( vue-cli 的 webpack 模板已經(jīng)預(yù)先配置好)
Browserify + vueify
Rollup + rollup-plugin-vue
2.6、優(yōu)化 SourceMap
我們?cè)陧?xiàng)目進(jìn)行打包后褐隆,會(huì)將開(kāi)發(fā)中的多個(gè)文件代碼打包到一個(gè)文件中剖踊,并且經(jīng)過(guò)壓縮德澈、去掉多余的空格、babel編譯化后缴守,最終將編譯得到的代碼會(huì)用于線(xiàn)上環(huán)境镇辉,那么這樣處理后的代碼和源代碼會(huì)有很大的差別忽肛,當(dāng)有 bug的時(shí)候,我們只能定位到壓縮處理后的代碼位置础废,無(wú)法定位到開(kāi)發(fā)環(huán)境中的代碼罕模,對(duì)于開(kāi)發(fā)來(lái)說(shuō)不好調(diào)式定位問(wèn)題淑掌,因此 sourceMap 出現(xiàn)了,它就是為了解決不好調(diào)式代碼問(wèn)題的诈悍。
SourceMap 的可選值如下(+ 號(hào)越多兽埃,代表速度越快柄错,- 號(hào)越多,代表速度越慢, o 代表中等速度 )
開(kāi)發(fā)環(huán)境推薦:cheap-module-eval-source-map
生產(chǎn)環(huán)境推薦:cheap-module-source-map
原因如下:
cheap:源代碼中的列信息是沒(méi)有任何作用给猾,因此我們打包后的文件不希望包含列相關(guān)信息敢伸,只有行信息能建立打包前后的依賴(lài)關(guān)系恒削。因此不管是開(kāi)發(fā)環(huán)境或生產(chǎn)環(huán)境钓丰,我們都希望添加 cheap 的基本類(lèi)型來(lái)忽略打包前后的列信息;
module:不管是開(kāi)發(fā)環(huán)境還是正式環(huán)境琢歇,我們都希望能定位到bug的源代碼具體的位置梦鉴,比如說(shuō)某個(gè) Vue 文件報(bào)錯(cuò)了尚揣,我們希望能定位到具體的 Vue 文件,因此我們也需要 module 配置娜庇;
soure-map:source-map 會(huì)為每一個(gè)打包后的模塊生成獨(dú)立的 soucemap 文件 方篮,因此我們需要增加source-map 屬性藕溅;
eval-source-map:eval 打包代碼的速度非常快汁掠,因?yàn)樗簧?map 文件,但是可以對(duì) eval 組合使用 eval-source-map 使用會(huì)將 map 文件以 DataURL 的形式存在打包后的 js 文件中翠忠。在正式環(huán)境中不要使用 eval-source-map, 因?yàn)樗鼤?huì)增加文件的大小秽之,但是在開(kāi)發(fā)環(huán)境中吃既,可以試用下鹦倚,因?yàn)樗麄兇虬乃俣群芸臁?/p>
2.7、構(gòu)建結(jié)果輸出分析
Webpack 輸出的代碼可讀性非常差而且文件非常大愤诱,讓我們非常頭疼捐友。為了更簡(jiǎn)單匣砖、直觀地分析輸出結(jié)果,社區(qū)中出現(xiàn)了許多可視化分析工具对人。這些工具以圖形的方式將結(jié)果更直觀地展示出來(lái)牺弄,讓我們快速了解問(wèn)題所在宜狐。接下來(lái)講解我們?cè)?Vue 項(xiàng)目中用到的分析工具:webpack-bundle-analyzer?抚恒。
我們?cè)陧?xiàng)目中?webpack.prod.conf.js?進(jìn)行配置:
if(config.build.bundleAnalyzerReport) {varBundleAnalyzerPlugin =require('webpack-bundle-analyzer').BundleAnalyzerPlugin;webpackConfig.plugins.push(newBundleAnalyzerPlugin());}
執(zhí)行 ?$ npm run build --report??后生成分析報(bào)告如下:
2.8俭驮、Vue 項(xiàng)目的編譯優(yōu)化
如果你的 Vue 項(xiàng)目使用 Webpack 編譯,需要你喝一杯咖啡的時(shí)間遗遵,那么也許你需要對(duì)項(xiàng)目的 Webpack 配置進(jìn)行優(yōu)化,提高 Webpack 的構(gòu)建效率雄坪。具體如何進(jìn)行 Vue 項(xiàng)目的 Webpack 構(gòu)建優(yōu)化,可以參考作者的另一篇文章《?Vue 項(xiàng)目?Webpack 優(yōu)化實(shí)踐》
三绳姨、基礎(chǔ)的 Web 技術(shù)優(yōu)化
3.1飘庄、開(kāi)啟 gzip 壓縮
gzip 是 GNUzip 的縮寫(xiě),最早用于 UNIX 系統(tǒng)的文件壓縮谴仙。HTTP 協(xié)議上的 gzip 編碼是一種用來(lái)改進(jìn) web 應(yīng)用程序性能的技術(shù)晃跺,web 服務(wù)器和客戶(hù)端(瀏覽器)必須共同支持 gzip毫玖。目前主流的瀏覽器付枫,Chrome,firefox二打,IE等都支持該協(xié)議掂榔。常見(jiàn)的服務(wù)器如 Apache衅疙,Nginx饱溢,IIS 同樣支持,gzip 壓縮效率非常高潘鲫,通常可以達(dá)到 70% 的壓縮率挖函,也就是說(shuō)怨喘,如果你的網(wǎng)頁(yè)有 30K振定,壓縮之后就變成了 9K 左右
以下我們以服務(wù)端使用我們熟悉的 express 為例后频,開(kāi)啟 gzip 非常簡(jiǎn)單,相關(guān)步驟如下:
安裝:
npminstallcompression--save
添加代碼邏輯:
varcompression =require('compression');varapp = express();app.use(compression())
重啟服務(wù)膏执,觀察網(wǎng)絡(luò)面板里面的 response header更米,如果看到如下紅圈里的字段則表明 gzip 開(kāi)啟成功 :
3.2、瀏覽器緩存
為了提高用戶(hù)加載頁(yè)面的速度壳快,對(duì)靜態(tài)資源進(jìn)行緩存是非常必要的镇草,根據(jù)是否需要重新向服務(wù)器發(fā)起請(qǐng)求來(lái)分類(lèi),將 HTTP 緩存規(guī)則分為兩大類(lèi)(強(qiáng)制緩存竖伯,對(duì)比緩存)七婴,如果對(duì)緩存機(jī)制還不是了解很清楚的察滑,可以參考作者寫(xiě)的關(guān)于 HTTP 緩存的文章《深入理解HTTP緩存機(jī)制及原理》,這里不再贅述户盯。
3.3莽鸭、CDN 的使用
瀏覽器從服務(wù)器上下載?CSS、js 和圖片等文件時(shí)都要和服務(wù)器連接足淆,而大部分服務(wù)器的帶寬有限巧号,如果超過(guò)限制氮兵,網(wǎng)頁(yè)就半天反應(yīng)不過(guò)來(lái)泣栈。而 CDN 可以通過(guò)不同的域名來(lái)加載文件弥姻,從而使下載文件的并發(fā)連接數(shù)大大增加庭敦,且CDN 具有更好的可用性,更低的網(wǎng)絡(luò)延遲和丟包率 秧廉。
3.4疼电、使用 Chrome Performance 查找性能瓶頸
Chrome 的 Performance 面板可以錄制一段時(shí)間內(nèi)的 js 執(zhí)行細(xì)節(jié)及時(shí)間蔽豺。使用 Chrome 開(kāi)發(fā)者工具分析頁(yè)面性能的步驟如下。
打開(kāi) Chrome 開(kāi)發(fā)者工具沧侥,切換到 Performance 面板
點(diǎn)擊 Record 開(kāi)始錄制
刷新頁(yè)面或展開(kāi)某個(gè)節(jié)點(diǎn)
點(diǎn)擊 Stop 停止錄制