Vue 項(xiàng)目性能優(yōu)化—實(shí)踐指南(網(wǎng)上最全 / 詳細(xì))

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)目具有更高效的性能瓜晤、更好的用戶體驗(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)化佃牛。

辛苦整理良久淹辞,還望手動(dòng)點(diǎn)贊鼓勵(lì)~

github地址為:github.com/fengshi123/…,匯總了作者的所有博客俘侠,也歡迎關(guān)注及 star ~

一象缀、代碼層面的優(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毀和重建央星;也是惰性的:如果在初始渲染時(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ì)算屬性力喷,依賴其它屬性值刽漂,并且 computed 的值有緩存,只有它依賴的屬性值發(fā)生改變弟孟,下一次獲取 computed 的值時(shí)才會(huì)重新計(jì)算 computed 的值贝咙;

watch:?更多的是「觀察」的作用,類似于某些數(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ì)算窟她,并且依賴于其它數(shù)據(jù)時(shí),應(yīng)該使用 computed蔼水,因?yàn)榭梢岳?computed 的緩存特性震糖,避免每次獲取值時(shí),都要重新計(jì)算趴腋;

當(dāng)我們需要在數(shù)據(jù)變化時(shí)執(zhí)行異步或開(kāi)銷較大的操作時(shí)吊说,應(yīng)該使用 watch,使用 watch 選項(xiàng)允許我們執(zhí)行異步操作 ( 訪問(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 屬性。

推薦:

    v-for="user in activeUsers"

    :key="user.id">

    {{ user.name }}

    computed: {

    activeUsers: function () {

    return this.users.filter(function (user) {

    return user.isActive

    })

    }

    }

    復(fù)制代碼

    不推薦:

      v-for="user in users"

      v-if="user.isActive"

      :key="user.id">

      {{ user.name }}

      復(fù)制代碼

      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ì)象就再也不能被修改了毒坛。

      export default {

      data: () => ({

      users: {}

      }),

      async created() {

      const users = await axios.get("/api/users");

      this.users = Object.freeze(users);

      }

      };

      復(fù)制代碼

      1.5、事件的銷毀

      Vue 組件銷毀時(shí),會(huì)自動(dòng)清理它與其它實(shí)例的連接煎殷,解綁它的全部指令及事件監(jiān)聽(tīng)器屯伞,但是僅限于組件本身的事件。如果在 js 內(nèi)使用 addEventListene 等方式是不會(huì)自動(dòng)銷毀的豪直,我們需要在組件銷毀時(shí)手動(dòng)移除這些事件的監(jiān)聽(tīng)劣摇,以免造成內(nèi)存泄露,如:

      created() {

      addEventListener('click', this.click, false)

      },

      beforeDestroy() {

      removeEventListener('click', this.click, false)

      }

      復(fù)制代碼

      1.6顶伞、圖片資源懶加載

      對(duì)于圖片過(guò)多的頁(yè)面饵撑,為了加速頁(yè)面加載速度,所以很多時(shí)候我們需要將頁(yè)面內(nèi)未出現(xiàn)在可視區(qū)域內(nèi)的圖片先不做加載唆貌, 等到滾動(dòng)到可視區(qū)域后再去加載滑潘。這樣對(duì)于頁(yè)面加載性能上會(huì)有很大的提升,也提高了用戶體驗(yàn)锨咙。我們?cè)陧?xiàng)目中使用 Vue 的 vue-lazyload 插件:

      (1)安裝插件

      npm install vue-lazyload --save-dev

      復(fù)制代碼

      (2)在入口文件 man.js 中引入并使用

      import VueLazyload from 'vue-lazyload'

      復(fù)制代碼

      然后再 vue 中直接使用

      Vue.use(VueLazyload)

      復(fù)制代碼

      或者添加自定義選項(xiàng)

      Vue.use(VueLazyload, {

      preLoad: 1.3,

      error: 'dist/error.png',

      loading: 'dist/loading.gif',

      attempt: 1

      })

      復(fù)制代碼

      (3)在 vue 文件中將 img 標(biāo)簽的 src 屬性直接改為 v-lazy 语卤,從而將圖片顯示方式更改為懶加載顯示:

      復(fù)制代碼

      以上為 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)白屏的情況,不利于用戶體驗(yàn)荧库。如果我們能把不同路由對(duì)應(yīng)的組件分割成不同的代碼塊堰塌,然后當(dāng)路由被訪問(wèn)的時(shí)候才加載對(duì)應(yīng)的組件,這樣就更加高效了分衫。這樣會(huì)大大提高首屏顯示的速度场刑,但是可能其他的頁(yè)面的速度就會(huì)降下來(lái)。

      路由懶加載:

      const Foo = () => import('./Foo.vue')

      const router = new VueRouter({

      routes: [

      { path: '/foo', component: Foo }

      ]

      })

      復(fù)制代碼

      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?:

      npm install babel-plugin-component -D

      復(fù)制代碼

      (2)然后喜喂,將 .babelrc 修改為:

      {

      "presets": [["es2015", { "modules": false }]],

      "plugins": [

      [

      "component",

      {

      "libraryName": "element-ui",

      "styleLibraryName": "theme-chalk"

      }

      ]

      ]

      }

      復(fù)制代碼

      (3)在 main.js 中引入部分組件:

      import Vue from 'vue';

      import { Button, Select } from 'element-ui';

      Vue.use(Button)

      Vue.use(Select)

      復(fù)制代碼

      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 在客戶端將標(biāo)簽渲染成的整個(gè) html 片段的工作在服務(wù)端完成悔常,服務(wù)端形成的 html 片段直接返回給客戶端這個(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)銷頁(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 :

      npm install image-webpack-loader --save-dev

      復(fù)制代碼

      (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,

      }

      }

      ]

      }

      復(fù)制代碼

      2.2、減少 ES6 轉(zhuǎn)為 ES5 的冗余代碼

      Babel 插件會(huì)在將 ES6 代碼轉(zhuǎn)換成 ES5 代碼時(shí)會(huì)注入一些輔助函數(shù)堡纬,例如下面的 ES6 代碼:

      class HelloWebpack extends Component{...}

      復(fù)制代碼

      這段代碼再被轉(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ǔ)法

      復(fù)制代碼

      在默認(rèn)情況下聂受, Babel 會(huì)在每個(gè)輸出文件中內(nèi)嵌這些依賴的輔助函數(shù)代碼,如果多個(gè)源代碼文件都依賴這些輔助函數(shù)烤镐,那么這些輔助函數(shù)的代碼將會(huì)出現(xiàn)很多次蛋济,造成代碼冗余。為了不讓這些輔助函數(shù)的代碼重復(fù)出現(xiàn)炮叶,可以在依賴它們時(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?:

      npm install babel-plugin-transform-runtime --save-dev

      復(fù)制代碼

      (2)然后旧困,修改 .babelrc 配置文件為:

      "plugins": [

      "transform-runtime"

      ]

      復(fù)制代碼

      如果要看插件的更多詳細(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)用戶的流量和服務(wù)器的成本拗盒。

      每個(gè)頁(yè)面需要加載的資源太大,導(dǎo)致網(wǎng)頁(yè)首屏加載緩慢锥债,影響用戶體驗(yàn)陡蝇。

      所以我們需要將多個(gè)頁(yè)面的公共代碼抽離成單獨(dú)的文件痊臭,來(lái)優(yōu)化以上問(wèn)題 。Webpack 內(nèi)置了專門用于提取多個(gè)Chunk 中的公共部分的插件 CommonsChunkPlugin毅整,我們?cè)陧?xiàng)目中 CommonsChunkPlugin 的配置如下:

      // 所有在 package.json 里面依賴的包趣兄,都會(huì)被打包進(jìn) vendor.js 這個(gè)文件中。

      new webpack.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)系

      new webpack.optimize.CommonsChunkPlugin({

      name: 'manifest',

      chunks: ['vendor']

      })

      復(fù)制代碼

      如果要看插件的更多詳細(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)銷,如果你使用服務(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ì)用于線上環(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 代表中等速度 )

      1.png

      開(kāi)發(fā)環(huán)境推薦:cheap-module-eval-source-map

      生產(chǎn)環(huán)境推薦:cheap-module-source-map

      原因如下:

      cheap:源代碼中的列信息是沒(méi)有任何作用,因此我們打包后的文件不希望包含列相關(guān)信息冠桃,只有行信息能建立打包前后的依賴關(guān)系命贴。因此不管是開(kāi)發(fā)環(huán)境或生產(chǎn)環(huán)境,我們都希望添加 cheap 的基本類型來(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) {

      var BundleAnalyzerPlugin =? require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

      webpackConfig.plugins.push(new BundleAnalyzerPlugin());

      }

      復(fù)制代碼

      執(zhí)行?$ npm run build \--report?后生成分析報(bào)告如下:

      1.png

      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 的縮寫后室,最早用于 UNIX 系統(tǒng)的文件壓縮。HTTP 協(xié)議上的 gzip 編碼是一種用來(lái)改進(jìn) web 應(yīng)用程序性能的技術(shù)混狠,web 服務(wù)器和客戶端(瀏覽器)必須共同支持 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)步驟如下:

      安裝:

      npm install compression --save

      復(fù)制代碼

      添加代碼邏輯:

      var compression = require('compression');

      var app = express();

      app.use(compression())

      復(fù)制代碼

      重啟服務(wù),觀察網(wǎng)絡(luò)面板里面的 response header蝇恶,如果看到如下紅圈里的字段則表明 gzip 開(kāi)啟成功 :

      1.png

      3.2拳魁、瀏覽器緩存

      為了提高用戶加載頁(yè)面的速度,對(duì)靜態(tài)資源進(jìn)行緩存是非常必要的撮弧,根據(jù)是否需要重新向服務(wù)器發(fā)起請(qǐng)求來(lái)分類潘懊,將 HTTP 緩存規(guī)則分為兩大類(強(qiáng)制緩存,對(duì)比緩存)贿衍,如果對(duì)緩存機(jī)制還不是了解很清楚的授舟,可以參考作者寫的關(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 停止錄制

      1.png

      更多關(guān)于 Performance 的內(nèi)容可以點(diǎn)擊這里查看。

      總結(jié)

      本文通過(guò)以下三部分組成:Vue 代碼層面的優(yōu)化伤靠、webpack 配置層面的優(yōu)化捣域、基礎(chǔ)的 Web 技術(shù)層面的優(yōu)化;來(lái)介紹怎么去優(yōu)化 Vue 項(xiàng)目的性能宴合。希望對(duì)讀完本文的你有幫助焕梅、有啟發(fā),如果有不足之處卦洽,歡迎批評(píng)指正交流贞言!

      辛苦整理良久,還望手動(dòng)點(diǎn)贊鼓勵(lì)~

      github地址為:github.com/fengshi123/…阀蒂,匯總了作者的所有博客该窗,也歡迎關(guān)注及 star ~

      ?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
      • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蚤霞,隨后出現(xiàn)的幾起案子酗失,更是在濱河造成了極大的恐慌,老刑警劉巖昧绣,帶你破解...
        沈念sama閱讀 221,820評(píng)論 6 515
      • 序言:濱河連續(xù)發(fā)生了三起死亡事件规肴,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡夜畴,警方通過(guò)查閱死者的電腦和手機(jī)拖刃,發(fā)現(xiàn)死者居然都...
        沈念sama閱讀 94,648評(píng)論 3 399
      • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)斩启,“玉大人序调,你說(shuō)我怎么就攤上這事⊥么兀” “怎么了发绢?”我有些...
        開(kāi)封第一講書(shū)人閱讀 168,324評(píng)論 0 360
      • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)垄琐。 經(jīng)常有香客問(wèn)我边酒,道長(zhǎng),這世上最難降的妖魔是什么狸窘? 我笑而不...
        開(kāi)封第一講書(shū)人閱讀 59,714評(píng)論 1 297
      • 正文 為了忘掉前任墩朦,我火速辦了婚禮,結(jié)果婚禮上翻擒,老公的妹妹穿的比我還像新娘氓涣。我一直安慰自己牛哺,他們只是感情好,可當(dāng)我...
        茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
      • 文/花漫 我一把揭開(kāi)白布劳吠。 她就那樣靜靜地躺著引润,像睡著了一般。 火紅的嫁衣襯著肌膚如雪痒玩。 梳的紋絲不亂的頭發(fā)上淳附,一...
        開(kāi)封第一講書(shū)人閱讀 52,328評(píng)論 1 310
      • 那天,我揣著相機(jī)與錄音蠢古,去河邊找鬼奴曙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛草讶,可吹牛的內(nèi)容都是我干的洽糟。 我是一名探鬼主播,決...
        沈念sama閱讀 40,897評(píng)論 3 421
      • 文/蒼蘭香墨 我猛地睜開(kāi)眼堕战,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼脊框!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起践啄,我...
        開(kāi)封第一講書(shū)人閱讀 39,804評(píng)論 0 276
      • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎沉御,沒(méi)想到半個(gè)月后屿讽,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
        沈念sama閱讀 46,345評(píng)論 1 318
      • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吠裆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
        茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
      • 正文 我和宋清朗相戀三年伐谈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片试疙。...
        茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
      • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诵棵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出祝旷,到底是詐尸還是另有隱情履澳,我是刑警寧澤,帶...
        沈念sama閱讀 36,238評(píng)論 5 350
      • 正文 年R本政府宣布怀跛,位于F島的核電站距贷,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏吻谋。R本人自食惡果不足惜忠蝗,卻給世界環(huán)境...
        茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
      • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望漓拾。 院中可真熱鬧阁最,春花似錦戒祠、人聲如沸。這莊子的主人今日做“春日...
        開(kāi)封第一講書(shū)人閱讀 32,417評(píng)論 0 24
      • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至哟旗,卻和暖如春贩据,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背闸餐。 一陣腳步聲響...
        開(kāi)封第一講書(shū)人閱讀 33,528評(píng)論 1 272
      • 我被黑心中介騙來(lái)泰國(guó)打工饱亮, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人舍沙。 一個(gè)月前我還...
        沈念sama閱讀 48,983評(píng)論 3 376
      • 正文 我出身青樓近上,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親拂铡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子壹无,可洞房花燭夜當(dāng)晚...
        茶點(diǎn)故事閱讀 45,573評(píng)論 2 359