有在追蹤使用者體驗的各種心理學研究,應該都有聽過網頁開啟速度的 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 載入

那一個上萬字的網頁,只是放個 Web Font 而已,為什麼沒有 100 分? 因為網頁工程師就是該死啊!

第二招:延遲載入非必要的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 主要是測網頁首次顯示的首屏,如果改天增加一種評量方式,會把網頁從頭捲動到尾,那這種奧步又失效了。

這些社群套件各有不同的雷,例如 Customer Chat 在 LINE 瀏覽器會有登入之後還會再叫人登入,在 Andorid 行動裝置上的瀏覽器會讓網頁畫面卡住無法捲動,Page Plugin 會遇到封面圖跑不出來(hide_cover參數是false),但是換一張粉專封面圖就又可以…之類千奇百怪的問題。為了安全起見,盡量能改用純超連結,不要顯示即時資料的就好了。否則喜歡三不五時沒事找事做、幫 FB debug 的,就歡迎多多使用這些社群外掛套件的「原廠」嵌入碼。

第三招:用 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 ,而且在電腦螢幕的各寬度上需要替換不同圖片,這招還是慎用。

其他優化網頁流暢度或 CWV 的小招

要改善跑分,要針對一個網頁從輸入網址到連線到載入的整個流程,還有頁面上要顯示的每一項東西,找出更好的處理方法 。
但是實務上常常是為了讓頁面看起來「很豐富」「完成度很高」「達成客戶想要的效果」然後放一堆雜物,用一堆會讓頁面 Render 時 Reflow 及 Repaint 的寫法,還有頁面內一堆「歷史遺物」不改沒事,誰改壞了誰該死,又沒預算整個重做。所以有時候為了提升跑分,只能用一些障眼法,例如:

  • 預先載入之術,把一些外部載入的資源 url 設定到 link rel=preconnect, link rel=dns-prefetch
  • 優先載入之術,整個網頁開啟時要下載的資源大小是不變的,但是我們讓視覺上第一屏的東西最高優先載入,一開始要看到的圖(例如上版背景、logo、覆蓋在頁面最上層的進入廣告圖、輪播圖第一張…等)把圖檔路徑設定在 link rel=preload,但是如果上稿的人沒有網頁資訊概念,直接放一張 300 dpi 好幾 MB 的照片上去,link rel=preload 會讓網頁載入時整個卡住。
  • 區塊設定 min-height,減少 CLS 的問題發生
  • iframe, img 加 loading=’lazy’,讓一些不需要一開始就載入的東西延遲載入
  • 頁面加上 content-visibility: auto,這是 Chromium 85 開始支援的新屬性,可以優化整個網頁中,一開始不會看到的元素的載入方式,但像是本文案例1的上萬字 webfont 純文字頁面,有加沒加,對跑分完全沒影響。要普及到所有瀏覽器也不知道要等到何時。
  • 慎選 iconfont,例如像 font-awesome 3, Bootstrap 3 這種,引用了整包 css 和字體檔,但可能最後只用到一兩顆圖示?這種應該要考慮乾脆改用 SVG 就好了,減少頁面檔案的 request 連線數跟載入時間。或是那種 iconfont 檔案要放外網的,又為 pagespeed 跑分帶來許多不可控的因素。可以交叉測試看把 iconfont 的檔案跟本地網頁放在一起,還是放在 iconfont 的原伺服器或CDN,看哪一個可以讓 pagespeed 提升跑分。

講到「優化」,就牽涉到對於中國用語的問題,我的個人想法,除了一些會讓人聽起來不悅的,哪邊更接近現實、更能讓人理解,就用哪個,例如這邊台灣用語應該要用「最佳化」,但是論網頁開啟速度要達到最佳,應該是把網頁上對於視覺傳達毫無用途的雜物通通移除,所有會造成扣分的東西拿掉、非必要的東西通通不要放,才能叫最佳,但論現實情況,舊網站難道是要整個重寫嗎? 客戶可以接受他的網站變得像瀏覽器的閱讀模式一樣清爽嗎? 上架的人可以接受他的每一張圖片都要壓縮到勉強不會太模糊的臨界點嗎? 都是只能稍做微調,離最佳還遠的了。

讓網站在 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 (CWV)的使用者體驗指標新挑戰

文章發出不到兩個月,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, 最大內容繪製)時間嗎?

做了一些實驗,發現 LCP 的評量標準似乎有一些可議之處…

上方的範例頁面,只是一個非常簡單的靜態頁面,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 的立意基本上是好的,計算網頁可視區域中,最大的內容元件載入所需要的時間,簡單來說就是使用者要花多久才能看到首屏主視覺。但判定頁面上最大內容這回事,似乎也有很多莊孝維的地方?
官方的介紹說 web.deb – LCP,會認 video, img, svg 裡面的 image、有用 css 設 backgorund 的地方、塊狀元素,當成頁面上最大內容。

先試一下在網頁上用 YouTube 提供的嵌入語法,放一個 iframe 在網頁上。

LCP 計算失敗

網頁上只放了一段影片,畫面上最大的內容當然就是影片,但是卻測出載入時間 6.5 秒,LCP 算不出來,分數是問號的情況。
在影片下面加了一段文字,載入時間跟 LCP 卻神奇的降到 0.8 秒,分數在及格邊緣。

LCP 是計算網頁可視區域中,最大的內容元件載入所需要的時間? 真想把 Web Vital s 官方網頁的相關敘述印出來,然後壓著 Google 的工程師請他們把字吃下去。

LCP實驗

第二個實驗,LCP實驗範例網頁0LCP實驗範例網頁1,兩個範例網頁放置的圖文,引用的 webfont, js, css 檔案完全相同,但一個網頁開啟時會先顯示一個提示訊息,要按掉才能繼續看。

首屏主視覺和 UX 完全不一樣的兩個網頁,卻得到相同的得分?LCP真的是叫(Largest Contentful Paint, 最大內容繪製)時間嗎?還是 Lighthouse 的電腦程式假裝知道使用者看到的首屏畫面,但實際上錯誤百出,在不少情況卻會誤殺忠良?

所以如果想透過諸如網頁一打開時先顯示提示訊息、 loading 動畫之類的,來掩護其他真正的首屏視覺,避免因為 LCP 太長而被扣分?看起來沒這麼好作弊,勢必要花更多時間去嘗試。

LCP實驗範例網頁2,調整許多地方,讓 LCP 變成綠色的,但也才提升一丁點的 PageSpeed 總分(不到10分),非常適合沒事找事做的企業,或是想要去刁難資訊部門的時候使用。

LCP實驗

跑版的網頁,卻能在網頁視覺體驗的 LCP 評分項目拿到更高分

另一個北爛的實測,我們做了2個實驗對照頁面,裡面有一個使用 Swiper 套件的普通圖片輪播 slideshow 效果,使用 IE11 無法正常顯示的純 ES6 版本(網頁不用掛JQuery),整個網頁含圖片載入 size 約 400 KB。

LCP實驗2

檢測項目幾乎都是綠燈,只有LCP項目的數值有相當大的落差,最終導致兩者差了快10分,但網頁程式碼就只差了幾個字。
分數較低的那個,我們讓輪播廣告內的大圖片在手機上會與螢幕同寬 100% 顯示,等比例縮小,就是正常網站的做法。
而分數較高的那個,則是完全不限制圖片寬度,在手機上看,圖片是會超出畫面外的,甚至讓網頁產生水平左右卷軸,就是一般人認知的網頁跑版。

測試其他網頁元素,好像只有圖片有此情況,94要讓畫面跑版凸出去,減少畫面 render 時間,才是高分的網頁體驗。
測試表格、iframe,卻沒有此情況,讓畫面跑版凸出去,或是符合畫面寬,分數都沒有多大的差異。

這就有趣了,一個跑版的網頁,卻能在網頁體驗的評分項目拿到更高分,機器真的能評斷出網頁體驗,還是實際上錯誤百出?

2021/04 update: Google Search Console 增加新版的網頁體驗報表

在 2021/4/19 時,Google Search Console 對於 網頁體驗 (Page Experience) 的項目做了改版,裡面有著非常直白的訊息「你的網站有沒有任何網址提供優質網頁體驗」

沒有裝 SSL 數位憑證的網站,就算網站使用體驗核心指標都是綠燈,似乎還是連討論的資格都沒有,一樣是「你的網站有沒有任何網址提供優質網頁體驗」….

Google 官方也公告說會在這些指標將會在今年六月開始影響搜尋引擎排序We’ll begin using page experience as part of our ranking systems beginning in mid-June 2021.,尖叫吧! 怒吼吧!

用 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 載入的廣告圖片,造成許多項目被扣分,如靜態資源相關的快取時間、可節省圖片尺寸部份等等
3.最上方自動置入內容的廣告版位區,引發畫面位移,導致CLS暴增
但是 AdSense 有規範不可以自己變更廣告程式,所以以上兩點基本上是無解的,除非設定只顯示純文字廣告。

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

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

結論

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

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

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

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

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

相關連結