1. 程式人生 > 其它 >Vue專案首屏開啟速度的優化

Vue專案首屏開啟速度的優化

Vue專案首屏開啟速度的優化

msfew ☁️sny.is  

專案的情況

我最近幾個月一直在參與VioLegacy網站的建設. 前端的技術棧是Vue. 說實話一開始參與的時候我是懵的, 因為沒怎麼用過Vue, 平常大多是用React, 後來我邊看邊學邊寫, 同時把樣式的部分所有的活都攬下來了, 這才到現在一直顯得很會寫Vue.

這幾周大家一直在搞SEO的事情, 我加了幾個<meta>標籤, 把SEO的評分算是完全拉滿了.

但是一跑Lighthouse發現, SEO比較差的緣故很可能主要是首頁開啟的效能問題...

 

原本以為會很低, 沒想到會這麼低. 這麼低的原因有兩個點:

  • 我們首頁有十幾張團隊成員的照片
  • 我們所用的Vue框架, 是需要載入JS然後注入到HTML裡的

圖片載入導致的效能問題

網站的底部有每個團隊成員的照片, 程式碼結構類似這樣:

<div class="team-member">
  <img
    class="round-image"
    src="@/images/VL-XXXXX.jpg"
    alt="VL-Edward.jpg"
    loading="lazy"
  />
  <h4>XXXX XXX XXX</h4>
  <p>XXX XXXXX, 2020</p>
  <p>University of XXX, 2021</p>
  </div>

像這樣的部分還有十幾個, 而且由於都是自發上傳的照片, 有些相機拍攝的照片特別大. 這絕對是一個網站載入時的大隱患.

懶載入Lazy Loading

img標籤內, 加上loading="lazy", 這樣可以讓圖片只有在視窗內的時候才載入.

這樣能夠減少不需要的載入時間.

但是由於我們的程式碼中, 已經將圖片進行了分批展示, 所以優化效果不明顯

圖片大小壓縮

之前提到一些相機拍攝的照片很大, 所以我直接想到了用tinypng來壓縮圖片的大小.

png是無損的圖片格式, 可以無失真壓縮; jpg是有損的, 壓縮時可能會受到一些小破壞. 同時也可以手動修改圖片尺寸來減少圖片大小.

直接把十幾張圖片拖進去壓縮後下載替換即可. 這一步讓我們網站的圖片總大小減少了50%. 但是還是優化不明顯.

JS載入導致的效能問題

經過圖片資源大小的優化, 我們發現好像並沒有什麼用. 大頭依然是JS的載入.

Prerender?

Vue的團隊成員做過一個預先渲染的外掛. 這個外掛配置很方便, 可以預先渲染一些檔案, 然後提高載入速度.

PrerenderSSR不同.

SSR是使用者進入網址後, 把JS先送到伺服器渲染完HTML再給客戶端; Prerender是構建時通過一個無頭瀏覽器去渲染出HTML.

SSR會增加伺服器的壓力, 配置麻煩; Prerender會很大拖慢構建的速度, 就連渲染一個網址也需要十秒左右的時間.

由於我們的需求只是渲染首頁, 所以我選擇了Prerender.

經過簡單的配置, 生成了一個充滿內容的HTML檔案, 但是一執行, 怎麼還是需要載入那麼多JS. 於是我看了下生成的檔案, 發現裡面資料都是缺失的, 而且樣式也是. 問題大了.

因為Prerender還有一個問題是不怎麼適用於動態資料很多的頁面... 如果想要把動態資料也帶上, 需要給根元件設定一個定時器, 讓它把資料拿完再渲染. 那麼可能就意味著, 開發時每次構建都得額外等個5秒等資料, 這就有點得不償失了, 甚至還不如咬咬牙上SSR.

Code Splitting

之後我搜索了一些優化相關的內容, 發現可以通過修改router來做到元件的按需載入.

我清晰地記得之前有看到過我們的router, 因為它是長這樣的.

import Official from '../views/Official.vue'
import LogIn from '../views/LogIn.vue'
import SignUp from '../views/SignUp.vue'
import StudentSignUp from '../views/SignUp/StudentSignUp.vue'
import AlumniSignUp from '../views/SignUp/AlumniSignUp.vue'
import Verification from '../views/Verification.vue'
import Main from '../views/Main.vue'
import Home from '../views/Main/Home.vue'
import MyWishesDetail from '../views/Main/MyWishesDetail.vue'
import WishList from '../views/Main/WishList.vue'
import WishListSenior from '../views/Main/WishListSenior.vue'
import WishCompany from '../views/Main/WishCompany.vue'
import Opportunities from '../views/Main/Opportunities.vue'
import Messages from '../views/Main/Messages.vue'
import OppDetail from '../views/Main/OppDetail.vue'
import FAQ from '../views/Main/FAQ.vue'
import AccountSettings from '../views/Main/AccountSettings.vue'
import Dashboard from '../views/Main/Dashboard.vue'
import PostOppDetail from '../views/Main/PostOppDetail.vue'
import PostNewOpp from '../views/Main/PostNewOpp.vue'
import EditPostOpp from '../views/Main/EditPostOpp.vue'
import AdminPage from '../views/Main/AdminPage.vue'
import Report from '../views/Main/Report.vue'

我不會用router, 但是我大受震撼. 這會導致一個很可怕的問題, 就是一開始載入到router的時候, 會把所有的東西都import過來, 形成的bundle會巨大.

為了優化這個情況, 可以這樣做:

const routes = [
  {
    path: '/',
    name: 'Official',
    component: () => import('../views/Official.vue')
  }
......

把每個import修改成這樣, 就可以做到通過一個回撥函式, 按需import外部檔案來載入, 大大減少Bundle的大小.

React的router優化 也類似.

優化成果

 

 

通過我們強硬的手段, 網站效能從❤️提高到了 , 從37提高到了52, 提升了40%. 渲染時間從4.6s到2.6s, 減少了77%.

網站的效能大大提高, 使用者的互動也將大大提升.

課代表總結:

  1. 懶載入img標籤.
  2. tinypng來壓縮圖片的大小.
  3. 通過修改router來懶載入元件.
  4. 使用Prerender或者SSR.