本文將結合針對 SwissDev Jobs 網站的優化實踐,來介紹我們是如何把網站加載時間減少了 24% 的。
上週,我們有機會對 SwissDev Jobs 網站的性能進行了微調。
之所以要提升 SwissDevJobs.ch 網站性能,主要是基於以下兩方面原因:
-
良好的用戶體驗——即加載時間更短(且互動性更好)和使用時的愉悅感 ;
-
SEO—— 我們的流量嚴重依賴谷歌搜索,而且你也許知道谷歌比較青睞性能良好的網站(谷歌甚至在搜索控制檯中引入了速度報告)。
當你搜索“website performance basics”時,你會得到許多操作建議,例如:
- 靜態資源使用 CDN 並配置合理的緩存時間;
- 優化圖片尺寸和格式;
- 使用 Gzip 或 Brotli 壓縮;
- 減少非關鍵的 JS 和 CSS 代碼的大小。
針對以上這些建議,我們進行了部分改進。另外,由於我們的主頁面基本上是一個可過濾的列表(用 React 編寫的),我們引入了 react-window 來 每次渲染 10 個列表項,而不是 250 個。
所有這些都幫助我們極大地提升了網站性能,但從速度報告來看,我們還可以做得更好。
因此我們開始深挖更多不尋常的方法來讓我們的網站變得更快…現在看來,我們非常成功! 下面是這周的報告:
這個報告顯示,完整的加載時間減少了 24%!
我們是如何做到這一點的呢?
針對 JSON 數據使用 rel=“preload”
這條在 index.html 文件中的簡單代碼向瀏覽器表明:它應該在這個資源被來自 JavaScript 的 AJAX 或 Fetch 調用實際請求之前獲取。
當需要獲取數據的時候,它會從瀏覽器緩存中讀取而不是重新獲取。這幫助我們 減少了大約 0.5s 的加載時間。
我們很早就想實現這一點了,但是過去在 Chrome 瀏覽器中一直有問題而導致重複下載兩次。而現在它可以正常生效了。
在服務端實現超簡單的緩存
在實現了 JSON 預加載之後,我們發現職位列表的下載仍然是瓶頸所在(等待 0.8s 從服務器獲得響應)。因此,我們決定從服務端緩存入手:
首先,我們嘗試了node-cache,但令人吃驚的是,它並沒有優化獲取時間。
值得一提的是,/api/jobs 接口是一個簡單的 GetAll 接口,因此沒有太多的優化空間。
於是,我們決定使用一個 JS 變量來構建我們自己的簡易緩存。它看起來如下:
這裏唯一沒有顯示的是 post /jobs 接口,這個接口刪除了所有的緩存(cachedJobs = undefined)。
就是這麼簡單!又減少了 0.4s 的加載時間!
移除不必要的字體
我們最後動手的是我們加載的 CSS 和 JS 打包文件的大小。我們注意到,非必要的 font-awesome 文件超過 70KB。
同時,我們可能只使用其中 20% 的圖標。
我們是如何解決這個問題的呢?我們使用 icomoon.io 來選擇我們使用的圖標,然後創建我們自己瘦身過的圖標包。
結果呢?節省了 50KB!
這 3 項不尋常的改動幫助我們將網站的加載時間加速了 24%。或者,如其它一些報告顯示的,加速了 43%(達到了 1.2s)。
我們對這些改動很滿意。但是,我們相信仍然有優化的空間。
如果你有獨有的不尋常的技術可以幫助我們——請告知我們!
加分點
在應用上述優化之後,我們注意到瓶頸仍然是獲取 /api/jobs 接口以及下載初始 HTML 的時間。其原因是,初始 HTML 以及這個 API 是由位於歐洲的一個單點服務器提供的。
我們尋找可行的解決方案,然後決定採用將一切都緩存在服務器層級的方案。
使用 Cloudflare,默認只有靜態資源會被緩存。但是,通過增加一個簡單的頁面規則,就可以啓用緩存任何頁面或資源的功能:
這使得我們的網站可以直接由 Cloudflare 的 CDN 提供服務,甚至不需要訪問服務器。
結果呢?
在世界各地的加載時間減少了 50%!
現在,你可能對緩存初始 HTML 和動態 API 的想法將信將疑,但請考慮:
- 首先,我們的接口不會頻繁改動——每天批量添加一次新的職位;
- 其次,我們在改動發生時,在程序中清除了緩存。
這使得我們可以在不到 1 秒的時間內將 SwissDev Jobs 服務到世界各地!
作者介紹:
SwissGreg,白天是程序員,晚上是獨立黑客——SwissDevJobs.ch。
原文鏈接: