Web 效能優化實戰之海外分校官網效能優化

語言: CN / TW / HK

前言:

加入到海外產研後得到一個需要 11 月底完成的任務:官網效能優化。

業務反饋網站開啟慢。

在這之前,前端的夥伴已經做了一些前期的工作,我翻閱了一下。

  • 三方指令碼報錯移除

  • 三方指令碼載入非同步處理

  • 非首屏圖片進行 lazy 載入處理

  • 非 SEO 必須元件使用非同步載入

01

第一個優化版本

基於 v-lazy-load 做了懶載入優化後,提交了一個版本給測試夥伴進行驗證,這時候遇到了一個問題:

沒有一個支援 CDN 加速的非線上環境

那就建立一個預釋出環境支援上 CDN 加速,就齊了

且慢,運維夥伴反饋:

由於二級域名過多,導致全集團加速的域名已經要超出套餐數量

為了達到套餐內能實現預釋出環境部署來驗證實際的優化效果,我們內部決定要做一輪 域名收斂  專項。經過這樣的處理後,將原始的  *.thethinkacademy.com  的路徑統一調整為  thethinkacademy.com/*  來節省域名資源。

經過這一輪調整後,終於可以來驗證一下之前的優化改動的效果了。

經過迴歸測試發現,沒有明顯的改善,新加坡的還在另一個指標上下降了 :frowning:

02

分析結果

我們現在使用 webpagetest  來進行效能測試,在之前的團隊裡我和夥伴們還做過基於  lighthouse  的效能分析和優化,這次也綜合參考了部分  lighthouse  的分析結果來改進。

一起看一下 webpagetest  的衡量指標:

  • Security Score

  • First Byte Time

  • Keep-Alive

  • GZIP text

  • Compress Images

  • Use Progressive JPEGs

  • Cache Static

  • Use A CDN

其中 Security Score First Byte Time  Cache Static  分均為  F  最低,其中  First Byte Time  是很重要的一個指標,即服務端開始給瀏覽器返回資料的標示;相比這個指標其實  lighthouse  首屏渲染  其實更有價值,現在先依據  webpagetest  的標準來進行優化。

03

優化方案

一般來說效能不好,無外乎這麼幾個點,其中非常容易做的就是靜態資源的壓縮和格式轉換,通過 lighthouse 分析可以發現,有一些大尺寸圖片以及一些體積巨大(600KB+)的圖片資源存在,這些資源對於載入效能影響巨大,需要消滅。

如何優化圖片體積,通過 webspeedtes.cloudin ary.com 來分析可以得到一個非常不錯的結果:

結果來看採用 AV1  編解碼的圖片格式  AVIF  一騎絕塵,但別忘了這個新格式在瀏覽器的支援上還不夠,不能直接預設啟用,還需要考慮 fallback 方案,而  webp  也是 Google 在推進的圖片格式同一樣有不錯的表現,但同樣為了做到各種瀏覽器的普適性,webp 都是一個需要考慮 fallback 方案的格式。這麼一來,從專案的時間風險來看需要考慮如下方案:

A. 採用原格式進行圖片壓縮;

B. 採用 JPEG2000 進行格式轉換(大部分情況下表現同樣亮眼);

C. 採用激進的 AVIF、webp 格式同樣考慮 fallback 格式。

為了支援多種圖片格式,需要將 <img> 換成 <picture> 

<picture>
<source srcset="mdn-logo.svg" type="image/svg+xml">
<source srcset="mdn-logo.avif" type="image/avif">
<source srcset="mdn-logo.webp" type="image/webp">
<img src="mdn-logo.png" alt="MDN">
</picture>

通過圖片壓縮工具 pngquant  可以將 1MB 的檔案壓縮到 400KB± 整體效果還是比較可觀的,而且處理起來的成本並不高,因此這個 A 計劃作為這個專案的首個版本會優先上線,後續增加對於 avif/webp 格式的嘗試來進一步節省空間和流量,到時候會進一步分享這部分的經驗。

安全性得分部分,根據測試結果的說明,可以較快確認解決方案:

  app.use(async (ctx, next) => {
ctx.set('Strict-Transport-Security', 'max-age=63072000')
ctx.set('X-XSS-Protection', '1; mode=block')
ctx.set('X-Frame-Options', 'DENY')
ctx.set('X-Content-Type-Options', 'nosniff')
await next()
})
<meta http-equiv="Content-Security-Policy" content="default-src https: http: 'self' 'unsafe-eval' 'unsafe-inline'; img-src data: https: http: 'unsafe-eval' 'unsafe-inline'; child-src https: http:; script-src https: http: 'unsafe-eval' 'unsafe-inline';">

應用上面的程式碼改動後,安全得分直接升級到 A

在後面測試過程中首屏載入時間指標在 A 和 B 之間反覆出現,通過分析結果來看出現在 JavaScript 以及 CSS 檔案過大,而這部分的優化則是一個相對複雜的過程,通過 webpack 打包的分析可以發現:

moment 以及 monent-timezone 是最大的那個包

前面 2 個 200KB+ 的包就是 moment 以及 momen t-timezone 真愁人,我查看了一下程式碼裡具體是如何使用 moment 以及 moment-timezone 的,發現其實我們並不需要這麼一個龐然大物來解決我們遇到的問題,本來還計劃基於 Intl 來自己做一套滿足要求的精簡版本來替代 moment 以及 moment-timezone 不過在調研的過程中,發現了  luxon 

通過專案地址 moment.github.io/luxon 可以發現,其實也是出自 moment 團隊的專案,這麼一來不需要自己重複造輪子了,經過一些程式碼的改動,包括查閱文件,通過了完整的編譯構建後,可以看看最終的結果:

優化了將近 200KB

對於 JavaScript 以及 CSS 的體積優化是一個相對中長期的過程,中間需要較多的程式碼整理、重構、甚至重新的技術選型。後面會繼續做這方面的嘗試和分享。

在使用 luxon 替換 moment 的過程中已經遇到了多處重複程式碼實現同樣的邏輯,這種就需要遵循 DRY 原則將他們消滅掉。

掃描下方二維碼新增 「好未來技術」 微信官方賬號

進入好未來技術官方交流群與作者實時互動~

(若掃碼無效,可通過微訊號 TAL-111111 直接新增)

- 也許你還想看 -

場景編排技術模型

深入理解網路IO複用併發模型

好未來輕舟業務閘道器效能提升之旅

我知道你“在看”喲~