有在追蹤使用者體驗的各種心理學研究,應該都有聽過網頁開啟速度的 X 秒原則,從西元二零零幾年到現在,在各種文獻都有不同的 X 數值,總之網頁開啟速度盡量越快越好。Google 也說過載入速度會當作SEO排名因素之一(Official Google Webmaster Central Blog: Using page speed in mobile search ranking),網站好不容易導流得到曝光,內容好不好先不論,卻敗在開啟速度,有點可惜,所以花時間調校,對於網站經營還是能有一丁點幫助的。

但什麼叫做讓網站變快?
– 在網站觀看線上視訊直播時,荷官和玩家…呃!老師和學生…之間的動作會有10秒以上的延遲
– 瀏覽供應商的產品資料網站,依SQL語法從70萬筆資料中篩選出對應的規格選項,要很久才能跑出結果
– 在論壇網站瀏覽別人的美食遊記,一篇文章有50張照片,開網頁開了老半天,文章都看完了,照片還沒跑完
– 瀏覽海外地區網站,點擊選單換頁,要過很長一段時間,畫面才會開始顯示內容
– 在網頁瀏覽器開啟雲端硬碟,上傳4K的行車紀錄器影片時,上傳的非常久

上述幾件事通通是在瀏覽網站時發生,但是慢的原因是完全不一樣的!
如果搞不懂哪些部份歸後端伺服器、哪些部分歸前端瀏覽器、哪些部分歸傳輸線路,就像騎 Gogoro 去加油站問說怎麼開油箱蓋、大鬧要加滿 92 汽油一樣,叫加油站的主管出來面對也沒用,是無法解決問題的。

像遇過有一次網頁打不開,圖片等靜態檔案載入,跟 ping domain, ip 都正常,就是有連到資料庫的後端程式都爆幹慢,某國內主機商匯X的回覆竟然是劈頭先丟 PageSpeed 跑分叫人把網頁裡的圖片壓縮,外行的”leader”還真的叫設計師開始壓圖片,實在是黑人問號。最後解決方式仍是伺服器重開機治百病。

本文純討論網頁開啟速度,現在最流行的就是使用 Google 出的 PageSpeed Insight, GTmetrix, Lighthouse, web.dev 之類的跑分檢測工具,就可以讓大家忙很久。

想提升 PageSpeed 的跑分,首先要先了解 PageSpeed 的計分方式:
– 用督導制,滿分100逐步扣下去,有做到的不會讚賞你,它覺得是缺失就扣爆
– PageSpeed 沒有暫存,一般瀏覽器都有暫存機制,初次瀏覽網頁時要下載一些圖片等靜態資源,但下次瀏覽時,只要沒有超過資料 Response 提供的檔頭資訊 Cache-Control , Etag …之類的有效期,會直接從本機暫存快取載入,第二次瀏覽時就會比較快,但是 PageSpeed 沒有這回事。
– 從 PageSpeed Insight 報告顯示出的伺服器首次回應速度,還有網站預覽圖,發現測試機的網路速度很慢,大概就是 Chrome DevTools 開到 Low-end mobile 的感覺。
– 分數不是固定值,網頁沒做修改,同一頁連測數次,分數會有上下浮動的情況,估計是受伺服器傳輸速度影響。那麼分數是要多測幾次取平均值、中位數,還是取最高分?還是取整個網站最高分的那頁?這裡開始就開始有統計爭議點了。

以下提供幾個小小的分數提升秘訣

第一招:換個方式載入 Google Fonts 的 Web Font

現代能上網的裝置這麼多,光是 iOS, Android, Windows 的黑體字都會長得不一樣,為了跨瀏覽器字型接近統一,或是有時候想讓網頁上的文字多些花樣,但又不想做成圖片,會用 Google Fonts 上的雲端字型,免費嘛!

Google fonts 提供的嵌入碼,是用 link tag 呼叫 css,本例在一個內文有上萬字的網頁裡直接直接引用,然後把這個極端環境的測試網頁1,直接丟去測 PageSpeed…
厲害了,不到10分(測試連結1)

PageSpeed - 使用 link tag 呼叫 web font css

不要聽從官方的嵌入碼指示,另外做一頁改用 Web Font Loader 來載入雲端字型,分數就能達到80分以上(測試連結2)

PageSpeed - 使用 webfont loader 載入

第二招:延遲載入非必要的JS套件,如 Facebook 的各種 plugins

從前 Flash 跟無名小站部落格的時代,部落格上常常掛一堆第三方套件,例如可愛日曆、部落格寵物、計數器,還有廣告之類的,最可怕的是網頁一打開還會自動播放音樂。

現在十幾年過去了,裝置的硬體效能提升了好幾倍,有線和無線網路的最大理論速度也提升了,網頁瀏覽器也吃了更多的記憶體,網頁瀏覽器對自動播放影音做了很多管制,但是網頁開起來一樣常常慢到靠北,因為網站可能仍然用低階伺服器和頻寬的省錢運作法,網站上仍然會放一些有的沒的第三方套件、廣告代碼、追蹤程式。

在本例的測試網頁,把台灣常見的「社群四天王」套件通通加好加滿
Line 分享按鈕與即時分享數
Facebook 分享按讚按鈕與分享數(like plugin)
Facebook 網頁內訊息聊天視窗(Customer Chat Plugin)
Facebook 粉絲專頁按讚區塊(page plugin)

除了四天王,常見的網頁嵌入還有 Google 地圖,Youtube影片、Facebook 留言板(Facebook Embedded Comments plugins)、Youtube 頻道訂閱按鈕(YouTube Subscribe Button)之類的,族繁不及備載…

PageSpeed - 嵌入社群分享套件

測試頁3丟去跑分之後發現,只是擺了一些分享按鈕,FB粉專按鈕,完全依照原廠指示放置嵌入碼,結果一個根本沒內容的空網頁… PageSpeed 分數就已經不及格了(測試連結3),而這些外部嵌入的東西通通都是別人網站上的程式,裡面的程式碼怎麼寫的,我們又管不著?

這時候要寫報告,由於社群行銷工具導致網頁開啟速度變慢,降低SEO的排名因素,看是這些社群套件要移除,還是行銷部門要裁…..當然不可能有這種事,最後還是該死的技術人員要處理。

一樣不要聽從官方的嵌入碼,自己把那些 Facebook, Line 嵌入碼改寫掉,例如先改寫成 lazyload 之類的機制,網頁開始捲動後,才載入這些社群網站套件。

PageSpeed - 延後載入嵌入社群分享套件
一個幾乎沒內容的空網頁測試頁4,也能回到比較正常的分數了。(測試連結4)。但因為目前 PageSpeed 主要是測網頁首次顯示的首屏,如果改天增加一種評量方式,會把網頁從頭捲動到尾,那這種奧步又失效了。

這些社群套件各有不同的雷,為了安全起見,盡量能改用純超連結,不要顯示即時資料的就好了。否則喜歡三不五時沒事找事做的,就歡迎多多使用社群套件「原廠」的嵌入碼。

第三招:用 picture 和 srcset 取代 RWD 的大小螢幕顯示不同張圖技巧

在 RWD 網站上的輪播廣告圖、圖文介紹之類的內容,視覺設計上可能需要針對大螢幕設計一套圖,手機小螢幕又設計另一套圖,最後再控制小螢幕顯示哪張圖,大螢幕顯示哪張圖、顯示位置之類的。

但是如果大小螢幕各要顯示哪張圖,只用純 CSS 的 display:none 去控制,打開瀏覽器的 Network 面板會發現,瀏覽器仍然會下載 display:none 的內容,消耗使用者端的網路下載流量和伺服器端的流量,就算用手機開網頁,實際上還是下載電腦+手機全部的圖片,相當浪費,不太環保。所以為了節省使用者和伺服器機房的網路頻寬,我們要改成浪費網頁設計人員的時間和青春、辦公室的冷氣、電力、網路。

改用 HTML5 的 picture 和 srcset,如 picture tag 的使用範例
<picture>
<source media="(min-width: 1023px)" srcset="https://blog.user.today/wp-content/uploads/2020/04/lcp-rank.jpg" />
<source media="(min-width: 300px)" srcset="https://blog.user.today/wp-content/uploads/2020/04/lcp-rank-254x300.jpg" />
<img src="https://blog.user.today/wp-content/uploads/2020/04/lcp-rank.jpg" alt="Sample" />
</picture>

在小螢幕上就只會載入 lcp-rank-254×300 那張圖,也可以讓 PageSpeed Insight 提升一點分數… 差了1分
PageSpeed - 使用 picture 和 srcset 載入

就算 HTML 包法變得這麼複雜,但要控制圖片的位置、透明度,CSS 一樣還是寫在 img 上面就好了。
但是,IE11 在 Caniuse 的 picture 和 srcset 都顯示紅色(不支援),只會永遠顯示最後那個 img tag 裡的圖,所以如果網頁必須支援在 IE11 ,而且在電腦螢幕的各寬度上需要替換不同圖片,這招還是慎用。

讓網站在 PageSpeed 測不出分數

有碰過幾個網站,有請主機商設定阻擋國外IP,只限台灣IP瀏覽,我不知道主機商是如何設定的,以及他們是用哪套國家 IP 資料表。總之這些設定阻擋國外訪客的網站,丟去測 PageSpeed 就只會出現以下訊息,跑不出分數。
Lighthouse returned error: FAILED_DOCUMENT_REQUEST. Lighthouse 無法穩定載入你要求的網頁。請確認你的測試網址是否正確,以及伺服器是否正確回應所有要求。(詳細資訊:net::ERR_TIMED_OUT) 結尾訊息有時候是 403 ERROR,有時候是 ERR_TIMED_OUT

限制國外 IP 除了會造成寄信問題跟 Google Ads 會變成廣告到達網址無效,也會造成 PageSpeed 問題。這也開啟了新思維,例如查主機 Log 檔,可以發現 PageSpeed bot 的 UserAgent 字串至少有以下兩種:
– Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36 Chrome-Lighthouse
– Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Mobile Safari/537.36 Chrome-Lighthouse
然後 IP 是66.249.82.* 開頭的,所以理論上可以針對 Chrome-Lighthouse 的 UserAgent 字串,或 IP 網段進行阻擋,甚至特別吐出不一樣的內容給 bot 看,來達成造假的目的…

Update: Core Web Vitals 的使用者體驗指標新挑戰

文章發出不到兩個月,2020/5月底的時候,Google 又發布了新的指標Official Google Webmaster Central Blog: Evaluating page experience for a better web,雖然說明年可能會實施(The ranking changes described in this post will not happen before next year,),但是現在從 Search Console 已經可以看到 LCP, CLS 相關的跑分出來靠腰了。

這次 Google 提出三大指標:
1.LCP(Largest Contentful Paint, 最大內容繪製)
2.FID(First Input Delay, 可互動時間時間)
3.CLS(Cumulative Layout Shift, 累計版面配置轉移)
這三大指標的意義在於企圖用程式算法來模擬評斷人類的「感覺」和 UX ,在 Lighthouse V6 版的計分比重 佔了頗大的比重,這下好了,就算網站放一堆沒人想看的內容,不針對目標使用者使用的搜尋意圖建置內容,反正只要有 SEO 問題就又可以推給工程師了。

這些評分標準會不會又限制創意,讓現代網頁的首屏畫面越長越像呢?客人可以接受「因為這個特效會拉高 LCP 時間,所以不要用」「貴公司的設計人員上傳圖片時,沒有 SEO 跟 CLS 的觀念」諸如此類的說法嗎??

本文後續將會繼續尋找玩弄 PageSpeed 機器的手法,以及哪些設計卻會讓這三個指標超低分的實驗。

簡單一行 CSS 就能讓 web.dev 的 accessibility 測不出分數

遇到一個網頁,在 web.dev 的 a11y 項目得分跑不出來,不知道是問號還是 0 分,Report 說明裡更是甚麼都沒寫,只有 Background and foreground colors have a sufficient contrast ratio – Error! 黑底白字能有什麼對比度問題?Google 又再整人了嗎?對,就是在整人。
web.dev 的 accessibility 分數異常

做了個可以重現問題的頁面webdev-a11y-fail,用蒙地卡羅法測了老半天,看看刪除頁面上哪一段 CSS 或 HTML 就能讓分數正常?
最後終於查出來。當要做一種效果:讓一段長度不固定的的文字在任何螢幕寬度都不要斷行,溢位的文字自動變成…,會使用 white-space:wrap 配合 text-overflow: ellipsis,雖然版面用一般瀏覽器看起來正常,但 white-space:wrap 竟然會讓跑分異常,向 web.dev 提交 bug 之後不知道有沒有機會解決。

PageSpeed 真的能正確計算首屏的 LCP(Largest Contentful Paint, 最大內容繪製)時間嗎?

上方的範例頁面,只是一個非常簡單的靜態頁面,2張圖片和 html 總共 56.5KB,GA 的檔案大約 52.6KB,在 LightHouse 的機器上面測 LCP 落在 1.9~4秒之間,一個內容跟寫法非常單純的網頁,LCP 評分項目已經差點進入不及格的邊緣了。
web vitals

現實的網頁當然不可能這麼單純,頁面上有一堆視覺上硬要放上去的雜物,為了RWD多出的CSS樣式碼和行動裝置操作元件,FB專頁按讚等第三方外掛,嵌入 Youtube、放思源黑體雲端字型、還有行銷公司要求追蹤碼一定要放在 head 裡面,還有整大包的 CSS framework, JavaScript framework,主機環境能省則省…等各種因素,別說 100 分,大部分的網頁都不及格。軟體開發的現實,絕非按照 optimize lcp 就可以完事的。

LCP 的立意基本上是好的,計算網頁可視區域中,最大的內容元件載入所需要的時間,簡單來說就是使用者要花多久才能看到首屏主視覺。但判定頁面上最大內容這回事,似乎也有些待改善之處?

LCP實驗
例如 LCP實驗範例網頁0LCP實驗範例網頁1,兩個範例網頁放置的圖文,引用的 webfont, js, css 檔案完全相同,但一個網頁開啟時會先顯示一個提示訊息,要按掉才能繼續看。首屏主視覺和 UX 完全不一樣的兩個網頁,卻得到相同的得分?LCP真的是叫(Largest Contentful Paint, 最大內容繪製)時間嗎?還是 Lighthouse 的電腦程式假裝知道使用者看到的首屏畫面,但實際上錯誤百出,在不少情況卻會誤殺忠良?

實際上仍要像 LCP實驗範例網頁2,調整許多地方,讓 LCP 變成綠色的,才有機會真的提升一丁點 PageSpeed 總分(不到10分),很適合沒事找事做的企業。
LCP實驗

用 LiteSpeed Web Server 會讓 PageSpeed 分數提高嗎?

這個部落格為了省錢或實驗性質,歷經多次搬家,最近一次也轉換到用 LiteSpeed Web Server 的虛擬主機,那這樣 PageSpeed Insight 分數有變高嗎?其實分數也沒差多少,而且自己會寫 JS 跟 CSS,用不著為了排版裝一堆 Elementor 之類的編輯器,套件能不裝的就盡量不裝,畢竟只是個單純的部落格而已,只差沒用 WordPress REST API 來自己做前台而已。

換了 LiteSpeed 之後,TTFB 跟之前的差不多,但前後台瀏覽的體感速度有變順,但扣分主要是在:
1.Google AdSense 廣告的 JavaScript 拉大了 render blocking 時間
2.AdSense 載入的廣告圖片,造成靜態資源相關的快取時間、可節省尺寸部份的審核項目被扣分
但是 AdSense 有規範不可以自己變更廣告程式,所以以上兩點基本上是無解的,除非設定只顯示純文字廣告。

所以在這種情況時,扣分數跟網站本身用哪一家主機商、啥伺服器架構沒關係。

這回到一開始騎 Gogoro 去加油站問說怎麼開油箱蓋的問題一樣,如果不了解慢的是哪些部份,例如用一年幾千塊的虛擬主機硬放了 N 個 WordPress 網站還裝了 WooCommerce 之類的肥外掛,導致網站速度慢,卻叫人要優化 CSS 跟 JS?操作後台經常執行到 timeout 或 5xx 當機,卻叫人壓縮圖片?那就繼續做夢,等哪一天網站真的會變快吧。

結論

衝分數跟搞資安的基本出發點有點像,多加任何一個東西上去,就要考慮會帶來怎樣的問題。但通常都是說加就加,為加而加,基層的技術人員就是該死。

衝分數不只是技術人員的事,編輯人員有沒有網頁插入圖片的正常觀念,製作適當大小的照片、適當的照片格式,也會大大的影響評分項目。

網頁一開始壓預算壓時程隨便寫,日後調整將會曠日費時、動搖國本、禍延子孫,創造更多的工作機會和商機。

網站前後端各自有許多可以調整的項目,但如果改善後讓 PageSpeed 分數提升,但實際體感並沒有變快,甚至有時反而變更慢?純屬正常現象。

至於如果是亂裝了一堆套件和佈景主題的 WordPress 網站,掛 AdSense 又設動態相關廣告的啦,甚至還是一整頁落落長的一頁式網站…也想要衝分數?沒錢沒時間就不要想太多了。