天天看點

如何優化Vue項目性能?

以下方式基于

@vue/cli

快速搭建的互動式項目腳手架

1. 路由懶加載

當打包建構應用時,JavaScript 包會變得非常大,影響頁面加載。如果我們能把不同路由對應的元件分割成不同的代碼塊,然後當路由被通路的時候才加載對應元件,這樣就更加高效了。

結合 Vue 的異步元件和 Webpack 的代碼分割功能,輕松實作路由元件的懶加載。

1 import Vue from 'vue'
 2 import Router from 'vue-router'
 3 import store from './store'
 4 import Home from './views/Home.vue'
 5 
 6 Vue.use(Router)
 7 
 8 const router = new Router({
 9   routes: [
10     {
11       path: '/',
12       name: 'home',
13       component: Home,
14     },
15     {
16       path: '/make',
17       name: 'make',
18       component: () => import(/* webpackChunkName: "make" */ './views/Make.vue'),
19     }
20   ],
21 })
           

2. webpack動态導入

将statically import(靜态導入) 改為 dynamic import(動态導入)進行代碼拆分

1 import(/* webpackChunkName: "html2canvas" */ 'html2canvas').then(
 2   ({ default: html2canvas }) => {
 3     html2canvas(document.querySelector('.container'), {
 4       scale: window.devicePixelRatio,
 5       allowTaint: false,
 6       useCORS: true,
 7     }).then(canvas => {
 8       console.log(canvas.toDataURL('image/jpeg', 0.9))
 9     })
10   }
11 )
           

3. 預取/預加載子產品(prefetch/preload module)

在聲明 import 時,使用下面這些内置指令,可以讓 webpack 輸出 "resource hint(資源提示)",來告知浏覽器:

  prefetch(預取):将來某些導航下可能需要的資源

  preload(預加載):目前導航下可能需要資源

import(/* webpackPrefetch: true */ 'LoginModal');

import(/* webpackPreload: true */ 'ChartingLibrary');           

這會生成

<link rel="prefetch" href="login-modal-chunk.js">

并追加到頁面頭部,訓示着浏覽器在閑置時間預取 login-modal-chunk.js 檔案。

隻要父 chunk 完成加載,webpack 就會添加 prefetch hint(預取提示)。

與 prefetch 指令相比,preload 指令有許多不同之處:

  • preload chunk 會在父 chunk 加載時,以并行方式開始加載。prefetch chunk 會在父 chunk 加載結束後開始加載。
  • preload chunk 具有中等優先級,并立即下載下傳。prefetch chunk 在浏覽器閑置時下載下傳。
  • preload chunk 會在父 chunk 中立即請求,用于當下時刻。prefetch chunk 會用于未來的某個時刻。
  • 浏覽器支援程度不同。

vue預設開啟,可在vue.config.js中全局禁用prefetch,再針對指定子產品開啟。

chainWebpack: config => {
  config.plugins.delete('prefetch')
},
           

4. 添加Gzip打包配置(compression-webpack-plugin)

yarn add compression-webpack-plugin -D

configureWebpack: config => {
  const CompressionPlugin = require('compression-webpack-plugin')
  config.plugins.push(new CompressionPlugin())
}
           

5. 添加頁面預渲染(prerender-spa-plugin)

在單頁應用程式中預呈現靜态HTML,可以極大的提高網頁通路速度,而且配合一些meat插件,基本可以滿足SEO需求。

預渲染基本上是在啟動無頭浏覽器,加載應用程式的路由并将結果儲存到靜态HTML檔案中。然後将其與以前使用的任何靜态檔案服務解決方案一起使用,是無需更改代碼或添加伺服器端渲染的解決方法。

不過,它僅适用于HTML5 history,因為每個預渲染的路由都會生成一個對應的HTML,在hash模式下使用隻會有一個HTML。

  

yarn add prerender-spa-plugin -D

1 configureWebpack: config => {
 2   const path = require('path')
 3   const PrerenderSPAPlugin = require('prerender-spa-plugin')
 4   config.plugins.push(
 5     new PrerenderSPAPlugin({
 6       staticDir: path.join(__dirname, 'dist'),
 7       routes: ['/'],
 8       minify: {
 9         collapseBooleanAttributes: true,
10         collapseWhitespace: true,
11         keepClosingSlash: true,
12         decodeEntities: true,
13         sortAttributes: true,
14       },
15       renderer: new PrerenderSPAPlugin.PuppeteerRenderer({
16         renderAfterDocumentEvent: 'render-event',
17         renderAfterTime: 5000,
18         // headless: false,
19       }),
20     })
21   )
22 }
23 
24 new Vue({
25   router,
26   store,
27   render: h => h(App),
28   mounted() {
29     // 預渲染 renderAfterDocumentEvent.
30     document.dispatchEvent(new Event('render-event'))
31   },
32 }).$mount('#app')
           

prerender-spa-plugin 利用了 Puppeteer 的爬取頁面的功能。 Puppeteer 是一個 Chrome官方出品的 headlessChromenode 庫。它提供了一系列的 API, 可以在無 UI 的情況下調用 Chrome 的功能, 适用于爬蟲、自動化處理等各種場景。它很強大,是以很簡單就能将運作時的 HTML 打包到檔案中。原理是在 Webpack 建構階段的最後,在本地啟動一個 Puppeteer 的服務,通路配置了預渲染的路由,然後将 Puppeteer 中渲染的頁面輸出到 HTML 檔案中,并建立路由對應的目錄。

6. 壓縮js,删除console(terser-webpack-plugin)

yarn add terser-webpack-plugin -D

1 configureWebpack: config => {
2   const TerserPlugin = require('terser-webpack-plugin')
3   config.optimization.minimizer.push(
4     new TerserPlugin({
5       extractComments: false,
6       terserOptions: { compress: { drop_console: true } },
7     })
8   )
9 }
           

7. bundle 分析(webpack-bundle-analyzer)

将 bundle 内容展示為便捷的、互動式、可縮放的樹狀圖形式。

yarn add -D webpack-bundle-analyzer

1 configureWebpack: config => {
2   const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
3     .BundleAnalyzerPlugin
4   config.plugins.push(new BundleAnalyzerPlugin())
5 }
           

8. WebP

WebP(發音 weppy),是一種支援有損壓縮和無損壓縮的圖檔檔案格式,派生自圖像編碼格式 VP8。根據 Google 的測試,無損壓縮後的 WebP 比 PNG 檔案少了 45% 的檔案大小,即使這些 PNG 檔案經過其他壓縮工具壓縮之後,WebP 還是可以減少 28% 的檔案大小。

不過WebP目前在IOS上相容性不好,可以使用JavaScript進行檢測,對支援 WebP 的使用者輸出 WebP 圖檔。

1 created() {
 2   const htmlClass = document.documentElement.classList
 3   this.checkWebpSupport() ? htmlClass.add('webps') : htmlClass.remove('webps')
 4 }
 5 
 6 checkWebpSupport() {
 7   try {
 8     return (
 9       document
10         .createElement('canvas')
11         .toDataURL('image/webp')
12         .indexOf('data:image/webp') === 0
13     )
14   } catch (err) {
15     return false
16   }
17 }
           

記一次BUG:

  在預設情況下,頁面加載完成執行

this.checkWebpSupport() && document.documentElement.classList.add('webps')

,沒有問題。

  但使用了prerender-spa-plugin進行預渲染後,因為執行預渲染的浏覽器是支援WebP的,所有會直接在頁面中加上'webps'類,是以即使浏覽器不支援WebP,不執行此方法也會有該類名。

9. 網頁性能優化測試(googlespeed)

進行網頁測試,根據優化建議針對性的修改,提高網頁加載速度。

https://www.googlespeed.cn/

如需上雲,可考慮如下阿裡雲伺服器,活動有優惠。

阿裡雲伺服器: 活動位址

購買前可測一下阿裡雲哪個節點的雲伺服器速度快:

https://ping.gaomeluo.com/aliyun/

原文:

https://blog.gaomeluo.com/archives/vuexingnengyouhua/

繼續閱讀