Vue的效能調校記錄

2020/05/30

架構

以下為我目前的系統架構

Web Server:AWS EC2 t2.micro(新加坡)

系統:ubuntu, 使用Nginx+php-fpm

Cloud Storage:AWS S3(新加坡)

 

Google Speed Insight

很多人在開發網站的時候

都會透過Google Speed Insight來幫網站做效能健診

並且透過分析報告來調整

但我在效能調校後的感想是

它提供的大部分的分析報告及修正建議是很有用的

但分數不能太過執著

 

先說建議的部份

會說大部分

是因為有些建議例如圖片縮圖

它會建議要用很小到很模糊的圖

但有些地方就是要顯示很大的圖所以沒辦法

 

再來有些是需要花錢來提昇的

因此要看當下的需求及預算來衡量

像是圖片來源的速度

我本身圖片是放在AWS S3上

如果願意多花一點錢把S3做加速

其實那個分數是會拉上很多

而且體感速度也是差很多

如果要再多花點錢用Cloudfront一定還會再更快更高分

所以有些調整是要看當下是否有辦法投入成本

 

再來

Google Speed Insight的爬蟲每次來爬的時候都是從美國出發

如果像我Server放在新加坡

速度上的物理限制很難突破

而且Google Speed Insight每次在分析的時候

都是在完全無Cache的情況

但在現實世界中其實都是第一次會比較慢

第二次開始就會快很多(當然前提是資源的cache設定要做好)

 

因此

我最後更在意的是體感速度的提昇

而不是完全的在追求Google Speed Insight的分數

 

Vuejs的部份

 

使用webpack splitchunk

vue+webpack在production的時候

如果沒特別處理

其實會發現很多超大的JS跟CSS

用Google Speed Insight它也會跟你說這些檔案太大了建議縮小

因此可使用webpack splitchunk將太大的js拆開

並設定每個cacheGroups的priority將比較不重要或少用的chunk排在後面

或是使用webpack magic comment設定webpackChunkName

 

另外

在針對production的js檔案大小及分佈

其實很難直接了解

所以我都使用webpack-bundle-analyzer來查看chunk的拆解情況

Screenshot_20200530_235808.png

 

Preload/Prefetch

在資源(js/css/font/image)的DOM attribute中加入preload/prefetch

可以決定載入的方式

preload: 在頁面render之前就開始載入, 比較重要的js就可以做preload

prefetch: 比較不重要或不常用的資源, 可以用prefetch, 瀏覽器將會在有空閒的時候背景載入, 要使用的時候就不需要再花時載入一次

這兩個載入方式都可以透過@vue/preload-webpack-plugin這個套件來處理

或是使用webpack magic commentwebpackPreloadwebpackPrefetch

 

preconnect

preconnect可以讓瀏覽器在對一些外部資源請求之前(像是後端的api, AWS S3, Google Analytics)

先對這些服務做DNS解析、或是交握等等這些動作

等到需要對這些Server請求的時候可以縮短一些時間

大概會長這樣

<link rel="preconnect" href="https://storage.googleapis.com" crossorigin>

 

一樣可以透過套件來完成(html-webpack-preconnect-plugin)

 

purgecss-webpack-plugin

這個套件會使用purgecss

可以拿來砍掉沒用到的css(Google Speed Insight會跟你說)

但要小心使用不要砍到真的要用的css

用Vue會有個問題就是因為production會將不是當下頁面的資源也載入

所以Google Speed Insight會跟你說你有些css沒用

但其實是在其他頁面有用到的

 

lazy load

使用lazy loading的好處

能讓畫面不可見範圍的資源像是圖片、影片等資源先不要載入

避免資源的浪費跟效能問題

npm上可以找到很多實做lazy load的js套件

我則是使用lazysizes

另外我有使用vuetify

vuetify本身也提供lazy load的相關功能

 

Web Server的部份

 

HTTP2

速度比HTTP1快

  • 可以對請求進行header壓縮
  • 多個請求只須建立單一TCP連線, 減少重複交握的時間
  • Server Push將資源Push到瀏覽器Cache中

 

Cache靜態資源

Web Server針對webpack打包後的靜態資源

做cache設定

其實就是幫靜態資源的header加上Cache-Control告訴瀏覽器cache起來

max-age的時間就依照需求設定

如果webpack有設定打包時重新將檔案hash

max-age其實可以拉長到一年都沒差

因為有新的發佈檔案都會更改

 

以下為nginx的範例

location ~ (css|js|map|jpg|jpeg|png|ico|gif|woff|woff2|svg|ttf|eto|br|gz)$ {
    add_header Cache-Control "max-age=86400";
}

 

JS/CSS minify

這個算是很基本的就不多講了

透過webpack都很好處理

Vue CLI建立的專案基本上也都預設有做到

 

瀏覽器相容性支援

這個就很取決系統的使用者瀏覽器使用比例

或是看專案合約上的瀏覽器支援

因為如果瀏覽器要支援比較舊的總是要透過polyfill

打包後也是很佔空間

如果專案不須特別支援ES5的話

polyfill就可以直接拿掉節省資源

或是直接使用Vue的Modern Mode打包

 

整個頁面初始化的時候加入loading

loading可以減少使用者對等待的焦慮感

一片白的頁面會讓人不知道網站是否正常運作

Google Speed Insight也會用空白的時間長度來做一部分的評斷

 

Cloud Storage的部份

 

Cache-Control設定

跟Web Server設定一樣

幫檔案加上Cache Control並設定TTL即可

Laravel在檔案上傳(put/putfileAs)選項就能直接對Cloud Storage做這些事情

<?php

Storage::disk('s3')->putfileAs('blog/foobar.jpg', $image, 'foobar.jpg', [
    'CacheControl' => 'max-age=31536000',
]);

 

金錢手段能處理的部份

有些事情靠金錢也能解決

單看當下的需求、預算

  • Web Server Instance開好一點
  • Cloudfront
  • S3加速

 

以Web Server Instance來說

因為我自己的Blog主要拿來做記錄用

所以也不會開多好夠用就好