提高在線商店的性能(案例研究)
已發表: 2022-03-10每個前端開發人員都在追逐同樣的性能聖杯:Google Page Speed 的綠色分數。 工作做得好的明顯跡象總是受到讚賞。 但是,就像尋找聖杯一樣,您必須質疑這是否真的是您正在尋找的答案。 您的用戶的真實性能以及網站在您使用它時的“感覺”不應該被打折,即使它會花費您一兩點的頁面速度(否則,我們都只會有一個搜索欄並且沒有樣式文本)。
我在一家小型數字代理機構工作,我的團隊主要在大型企業網站和商店工作——頁面速度有時會成為討論的焦點,但通常到那時答案是需要大量重寫才能真正實現任何目標,公司規模和項目結構的不幸副作用。
在其在線商店上與 Jewellerybox 合作對我們來說是一個可喜的變化。 該項目包括將商店軟件升級到我們自己的開源系統,並從頭開始重做商店的前端。 該設計是由一個設計和用戶體驗機構製作的,該機構還處理 HTML 原型(基於 Bootstrap 4)。 從那裡,我們將它整合到模板中——這一次,我們有一個客戶也痴迷於網站的性能。
對於發布,我們主要專注於推出新設計,但網站重新啟動後,我們開始將注意力集中在將紅色和橙色分數變為綠色。 這是一個充滿艱難決定的多月旅程,有很多關於哪些優化值得追求的討論。 今天,該網站速度更快,並且在各種展示和基準測試中排名很高。 在本文中,我將重點介紹我們所做的一些工作以及我們如何能夠達到我們的速度。
在線商店有點不同
在我們詳細介紹之前,讓我們花一點時間來談談在線商店與許多其他網站的不同之處(如果您已經知道這一點,我們將在下一節中與您見面)。 當我們談論電子商務網站時,您將擁有的主要頁面是:
- 主頁(和“內容”頁面),
- 類別和搜索頁面,
- 產品詳細信息頁面,
- 購物車和結帳(顯然)。
在本文中,我們將重點關注前三個以及針對這些的性能調整。 結帳是它自己的野獸。 在那裡,您將有很多額外的 JavaScript 和後端邏輯來計算價格,加上幾個服務調用來獲取適當的運輸提供商和基於運送到的國家/地區的價格估計。
這顯然是除了驗證您需要記錄帳單和送貨地址的表單字段之外。 再加上支付提供商的插件,您自己就有了一些頁面,一旦它們經過適當的測試和工作,就沒有人願意觸摸它們。
當您想像在線商店時,您首先想到的是什麼? 圖片——大量的產品圖片。 它們基本上無處不在,並將主導您的設計。 另外,您將希望展示許多產品以吸引人們向您購買 - 所以它是一個輪播。 可是等等! 人們會點擊其中的產品嗎? 我們可以通過在輪播上放置一些跟踪來找出答案。 如果我們跟踪它,我們可以優化它! 突然間,我們的頁面上出現了由 AI 驅動的外部產品輪播。
問題是,輪播不會是您添加到頁面以展示更多產品以吸引更多銷售的最後一個速度懲罰元素。 當然,商店需要互動元素,無論是產品圖像縮放、一些視頻、今天發貨截止日期的倒計時,還是與客戶支持聯繫的聊天窗口。
當您直接將轉化作為收入來衡量時,所有這些都非常重要。 另外,每隔幾個月,團隊中的某個人就會發現一些可以添加的很酷的新功能,因此復雜性和 JavaScript 開始累積,即使您一開始就打算保持精簡。
雖然您通常可以緩存文章的整頁,但許多商店頁面和元素並非如此。 有些是特定於用戶的,例如標題中的購物車或願望清單,由於數據的個人性質,它們永遠不應該被緩存。 此外,如果您有實物商品,您將處理實時庫存:尤其是在聖誕節高峰期,您需要準確和最新的庫存信息; 因此,您將需要一個更複雜的緩存策略,允許您緩存頁面的某些部分,並在服務器端呈現期間將所有內容重新組合在一起。
但即使在規劃階段,陷阱也在等待。 在設計中——通常也是原型階段——你將使用精心製作的產品名稱和描述,長度幾乎一致,以及理想的產品圖像。 他們看起來棒極了! 唯一的問題? 實際上,產品信息的長度可能會非常不同,這可能會弄亂您的設計。 擁有數千種產品,您無法逐一檢查。
因此,如果設計師或進行原型測試的人員使用非常短和非常長的字符串來確保設計仍然合適,這將有所幫助。 同樣,信息在 HTML 中出現兩次,一次用於桌面,一次用於移動,對於商店來說可能是一個大問題 - 特別是如果它是複雜信息,如產品詳細信息、購物車或產品類別過濾器的方面頁。 讓它們保持同步是很難做到的——所以,請幫助其他開發人員,不要這樣做。
另一件不應該是事後考慮並且應該從原型階段開始就被納入的事情是可訪問性。 有幾種工具可以幫助您了解一些基礎知識,從為所有圖像和圖標提供具有功能的替代文本,到顏色對比,再到了解在何處(以及何時不使用)使用哪些 ARIA 屬性。 從一開始就加入這一點比後來容易得多,它讓每個人都可以享受你正在開發的網站。
這裡有一個提示:如果您還沒有看到人們使用屏幕閱讀器或僅使用鍵盤進行導航,則可以在 YouTube 上輕鬆找到有關這方面的視頻。 它將改變您對這些主題的理解。
回歸業績:為什麼再次提升店鋪業績如此重要? 顯而易見的答案是,您希望人們向您購買。 有幾種方法可以影響這一點,您的網站速度很重要。 研究表明,每增加一秒的加載時間都會對轉化率產生重大影響。 此外,頁面速度是搜索和 Google Ads 的排名因素。 因此,提高績效將對底線產生實實在在的影響。
我們做過的實際事情
一些性能瓶頸很容易識別,但徹底的改進是一段漫長的旅程,曲折多。 我們從所有常見的事情開始,例如重新檢查資源的緩存,查看我們可以預取或異步加載的內容,確保我們使用的是 HTTP/2 和 TLSv1.3。 其中許多都包含在 CSS-Tricks 的有用概述中,Smashing Magazine 提供了一個很棒的 PDF 清單。
第一件事:所有頁面上加載的東西
讓我們談談資源,而不僅僅是 CSS 或 JavaScript(我們將在後面介紹)。 我們首先查看跨多個屏幕共享的內容,每個屏幕都會產生影響。 只有在那之後,我們才專注於頁麵類型和它們特有的問題。 一些常見的項目如下。
圖標加載
與許多網站一樣,我們在設計中使用了幾個圖標。 原型帶有一些嵌入 SVG 符號的自定義圖標。 這些作為一個大的svg
標記存儲在頁面的 HTML 頭部中,每個圖標都有一個符號,然後用作 HTML 正文中的鏈接svg
。 這具有在文檔加載時使它們直接可供瀏覽器使用的良好效果,但顯然瀏覽器無法為整個網站緩存它們。
所以我們決定將它們移動到一個外部 SVG 文件並預加載它。 此外,我們只包含了我們實際使用的圖標。 這樣,文件可以緩存在服務器和瀏覽器中,不需要解釋多餘的 SVG。 我們還支持在頁面上使用 Font Awesome(我們通過 JavaScript 加載),但我們按需加載(添加一個檢查任何<i>
標籤的小腳本,然後加載 Font Awesome JavaScript 以獲取任何 SVG它找到的圖標)。 因為我們堅持使用自己的首屏圖標,所以我們可以在 DOM 加載後運行整個腳本。
我們還在某些地方將表情符號用於彩色圖標,這是我們沒有人真正想到的,但我們的內容編輯 Daena 要求這樣做,這是顯示圖標的好方法,對性能沒有任何不利影響(唯一需要注意的是不同操作系統上的不同設計)。
字體加載
像在許多其他網站上一樣,我們使用網絡字體來滿足我們的排版需求。 該設計要求正文中使用兩種字體(兩種粗細的Josefin Sans ),一種用於標題( Nixie One ),一種用於特殊樣式的文本( Moonstone Regular )。 從一開始,我們將它們存儲在本地,使用內容交付網絡 (CDN) 來提高性能,但在閱讀了 Simon Hearne 關於避免字體加載時佈局變化的精彩文章後,我們嘗試刪除粗體版本並使用常規版本。
在我們的測試中,視覺差異是如此之小,以至於我們的測試人員都無法在不同時看到兩者的情況下分辨出來。 所以,我們去掉了字體粗細。 在撰寫本文並為本節準備視覺輔助材料時,我們偶然發現 Mac 上基於 Chromium 的瀏覽器與高分辨率屏幕上基於 WebKit 的瀏覽器之間存在較大差異(耶,複雜!)。 這引發了關於我們應該做什麼的另一輪討論。
經過一番反复,我們選擇保持假粗體並使用-webkit-text-stroke: 0.3px
來幫助那些特定的瀏覽器。 與使用實際單獨字體粗細的區別很小,但對於我們的用例來說還不夠,我們幾乎不使用粗體字體,一次只使用幾個單詞(對不起,字體愛好者)。
此外,一些產品可以通過雕刻進行個性化。 這些雕刻可以用多種字體完成,對於某些字體,我們提供應用字體的預覽。 對於這些,我們在下拉字體選擇器中選擇字體時按需下載字體。 下拉列表中的預覽是字體外觀的示例圖像。 這使我們不必下載 10 個或更多額外的字體文件。
舊版支持
有一天,CSS-Tricks 發表了一篇關於“如何在 2021 年實現 Favicon”的文章,讓我大吃一驚。 我們使用了世界上所有尺寸的觸摸圖標——這篇文章讓我重新評估了我們真正需要的東西,並向我展示了有時幾年前的真實情況可能不再需要了。 根據這篇文章,我們將網站圖標和触摸圖標列表限制為推薦版本。
同樣,我們還將僅作為WOFF 版本的字體轉換為小得多的 WOFF2 ,我們決定為字體提供 WOFF2(保留 WOFF 作為後備)。 我們清除了不再需要的 CSS 指令。
延遲和按需加載
幾個指標集中在用戶可以與頁面交互的時間上。 邏輯表明,要加載的元素更少意味著將更快地達到這一點。 考慮到這一點,重要的是要問自己頁面的哪些部分是必不可少的,以及用戶以後才需要哪些部分。 我們對此進行了很多辯論和反複試驗。
網絡活動的瀑佈在這裡有很大幫助,但對用戶流的思考也是如此。 例如,縮放後的產品圖片可以在用戶第一次與產品圖片交互時加載,而頁腳中的圖片通常不會顯示在首屏,可以稍後加載。 如果您擔心速度變慢,您仍然可以使用預取資源。
我們很早就注意到的一件事是聊天客戶端的巨大影響。 僅 JavaScript 就超過 500 KB,雖然很遺憾我沒有圖表,但加載速度也很慢。 儘管 JavaScript 被設置為異步加載,Google 還是將其包含在交互時間測量中。
我們無法完全追踪為什麼會出現這種情況,但在它和它的龐大規模之間,我們開始尋找替代方案,而不是試圖修復我們控制有限的東西。 我們說服Jewellerybox嘗試使用自託管的開源聊天小部件,這讓我們可以更好地控制它的加載方式,而且體積也更小。 為了進一步改進它,我們最初只加載聊天的圖標; 當您單擊打開它時,其餘部分會被加載。
隱形的第三方輪播
Jewellerybox 想嘗試一種第三方服務,該服務使用 AI 來改善多頁輪播中的產品個性化。 我們決定為此從後端調用它的 API,以便我們可以更好地控制加載的內容(沒有大的 JavaScript 依賴項)以及等待服務響應的時間(定義了一些後備)。 因此,輪播以與非個性化輪播相同的方式加載,並且也可以使用唯一的緩存鍵進行緩存。
但是有一個缺點:這意味著服務器端的初始頁面呈現可能會更慢,除非緩存。 出於這個原因,我們目前正在研究在頁面加載並首先呈現佔位符後注入結果的替代方法。
第二步:優化 JavaScript — 與外部敵人的艱苦戰鬥
輪播將我們帶到了我們關注的第二大領域:JavaScript。 我們審核了我們擁有的 JavaScript,其中大部分來自用於不同任務的庫,幾乎沒有自定義代碼。 我們優化了我們自己編寫的代碼,但顯然,如果它只是整個代碼的一小部分,那麼您可以做的只有這麼多——最大的收穫在於庫。
優化庫中的東西或取出不需要的部分很可能是愚蠢的差事。 您並不真正知道為什麼有些部件在那裡,並且如果沒有大量的手動工作,您將永遠無法再次升級庫。 考慮到這一點,我們退後一步,查看了我們使用哪些庫以及我們需要它們的用途,並為每個庫調查是否存在更小或更快的替代方案,同時也滿足我們的需求。
在幾種情況下,有! 例如,我們決定用 GliderJS 替換 Slick 滑塊庫,它具有更少的功能,但我們需要的所有功能,而且加載速度更快,並且具有更現代的 CSS 支持! 此外,我們從主要的 JavaScript 文件中取出了許多自包含的庫,並開始按需加載它們。
因為我們使用的是 Bootstrap 4,所以我們仍然在項目中包含 jQuery,但正在努力用本機實現替換所有內容。 對於 Bootstrap 本身,在 GitHub 上有一個 bootstrap.native 版本,沒有我們現在使用的 jQuery 依賴項。 它體積更小,運行速度更快。 另外,我們生成了兩個版本的主 JavaScript 文件:一個不包含 polyfill,另一個包含它們,當瀏覽器需要它們時,我們會與它們交換版本,使我們能夠為大多數人提供流線型的主版本。 我們測試了“按需填充”服務,但性能沒有達到我們的預期。
關於 jQuery 主題的最後一件事。 最初,我們從服務器加載它。 通過 Google CDN 加載測試系統時,我們看到了性能改進,但 Page Speed Insights 抱怨性能問題(我想知道誰能解決這個問題),所以我們再次測試自己託管它,在生產中它實際上更快,因為我們使用的 CDN。
經驗教訓:測試環境不是生產環境,對一個環境的修復可能不適用於另一個環境。
第三:圖像——格式、尺寸和所有爵士樂
圖像是構成在線商店的重要組成部分。 一個頁面通常會有幾十張圖片,甚至在我們計算不同設備的不同版本之前。 珠寶盒網站已經存在將近 10 年了,大部分時間都可以買到許多產品,因此原始產品圖片的尺寸和样式並不統一,產品照片的數量也可能會有所不同。
理想情況下,我們希望以現代格式為不同的視圖大小和顯示密度提供響應式圖像,但是任何需求的變化都意味著需要完成大量的轉換工作。 因此,我們目前使用優化尺寸的產品圖片,但我們沒有針對它們的響應式圖片。 更新是在路線圖上,但不是微不足道的。 內容頁面提供了更大的靈活性,我們在那裡生成和使用不同的大小,包括 WebP 和後備格式。
擁有如此多的圖像會增加初始有效負載的權重。 因此,何時以及如何加載圖像成為一個巨大的話題。 延遲加載聽起來像是解決方案,但如果普遍應用它可以減慢最初可見的圖像,而不是直接加載它們(或者至少對用戶來說是這樣的感覺)。 出於這個原因,我們選擇了直接加載前幾個和延遲加載其餘部分的組合,使用原生延遲加載和腳本的組合。
對於網站徽標,我們使用 SVG 文件,為此我們從客戶端獲得了初始版本。 徽標是一種錯綜複雜的字體,其中缺少部分字母,因為它們是手工完成的不完美印刷。 在大尺寸中,您需要顯示細節,但在網站上我們從不使用超過 150 x 30 像素的尺寸。 原始文件大小為 192 KB,不算大,但也不算超小。 我們決定使用 SVG 並減少其中的細節,我們最終得到了一個 40 KB 大小的解壓縮版本。 我們使用的顯示尺寸沒有視覺差異。
最後但絕對不是最不重要的:CSS
關鍵 CSS
CSS 在 Google 的 Chrome 用戶體驗報告 (CrUX) 中佔有重要地位,並且在 Google Page Speed Insights 報告和建議中也佔有重要地位。 我們做的第一件事是定義一些關鍵的 CSS,我們直接在 HTML 中加載它們,以便瀏覽器盡快使用它——這是對抗內容佈局轉換 (CLS) 的主要武器。 我們選擇了基於原型頁面的關鍵 CSS的自動提取和我們可以定義要提取的類名的機制(包括所有子規則)的組合。 我們對添加到相應頁麵類型的一般樣式、產品頁面樣式和類別樣式分別執行此操作。
我們從中學到的一點是,這導致了一些錯誤,那就是我們必須小心 CSS 的順序不會因此而改變。 在編寫代碼的不同人之間、稍後在文件中添加覆蓋的人以及提取內容的自動工具之間,它可能會變得混亂。
針對 CLS 的顯式維度
對我來說,CLS 是谷歌從它的帽子裡抽出來的東西,現在我們都需要處理它,並把我們的集體頭腦圍繞在它周圍。 以前,我們可以簡單地讓容器從其中的元素中獲取它們的大小,現在這些元素的加載可能會影響盒子的大小。 考慮到這一點,我們使用了開發人員工具中的“性能”選項卡和超級有用的 Layout Shift GIF 生成器來查看導致 CLS 的元素。 從那裡,我們不僅查看了元素本身,還查看了它們的父元素,並分析了會對佈局產生影響的 CSS 屬性。 有時我們很幸運——例如,標誌只需要在移動設備上設置一個明確的尺寸來防止佈局變化——但其他時候,鬥爭是真實的。
專業提示:有時變化不是由明顯的元素引起的,而是由它之前的元素引起的。 要確定可能的罪魁禍首,請關注大小和間距發生變化的屬性。 要問自己的基本問題是:什麼可能導致這個塊移動?
因為頁面上有這麼多圖像,使用 CLS 讓它們正確運行也需要我們做一些工作。 Barry Pollard 在他的文章“設置圖像的高度和寬度再次重要”中正確地提醒了我們這一點。 我們花了很多時間為每種情況下的圖像找出正確的寬度和高度值(加上縱橫比),以便再次將它們添加到 HTML 中。 結果,圖像的佈局不再發生變化,因為瀏覽器會提前獲取信息。
神秘的 CLS 分數案例
在刪除了頁面頂部附近的許多重大 CLS 問題後,我們遇到了障礙。 有時(並非總是)在查看 Page Speed 或 Lighthouse 時,我們的 CLS 得分超過 0.3,但從未出現在“性能”選項卡中。 Layout Shift GIF Generator有時會顯示它,但看起來整個頁面容器都在移動。
啟用網絡和 CPU 限制後,我們終於在屏幕截圖中看到了! 由於其中的元素,移動設備上的標題高度增加了 2 個像素。 因為標題在移動設備上是固定高度的,所以我們採用了簡單的修復並為其添加了顯式高度 - 案例關閉。 但這花費了我們很大的精力,這表明這裡的工具仍然很不精確。
這是行不通的——讓我們重做吧!
眾所周知,移動端的 Page Speed 分數比桌面端的分數要高得多,其中一個對我們特別不利的領域是產品頁面。 CLS 分數高居榜首,頁面也存在性能問題(幾個輪播、選項卡和不可緩存的元素會這樣做)。 更糟糕的是,頁面的佈局意味著一些信息被打亂或添加了兩次。
在桌面上,我們基本上有兩列內容:
- A 列:產品照片輪播,有時後面是博客引用,然後是帶有產品信息的選項卡式佈局。
- B 列:產品名稱、價格、描述和“添加到購物車”按鈕。
- C行:同類產品的產品輪播。
但是,在移動設備上,產品照片輪播需要先出現,然後是 B 列,然後是 A 列的選項卡式佈局。因此,某些信息在 HTML 中重複,由display: none
控制,並且訂單正在使用flex: order
屬性切換。 它確實有效,但對 CLS 分數不利,因為基本上所有內容都需要重新排序。
我決定在 CodePen 中進行一個簡單的實驗:我能否通過重新考慮 HTML 並使用display: grid
而不是 flexbox 在桌面和移動設備上實現相同的基本框佈局,這是否允許我根據需要簡單地重新排列網格區域? 長話短說,它奏效了,它解決了 CLS,它還有一個額外的好處,即現在產品名稱在 HTML 中出現的時間比以前快得多——增加了 SEO 勝利!
破解 CLS 的輪播
“輪播”這個詞已經出現了好幾次——而且有充分的理由。 我們不僅更改了我們使用的輪播庫(並更改了其中圖像的加載行為),我們還必須為 CLS 處理它,因為我們有幾個頁面上的輪播位於首屏,因此,可能會對速度分數產生很大影響。
我們先是稍後加載輪播以減少 time-to-interactive ,但這會導致明顯的延遲,直到 JavaScript 觸發並且幻燈片從彼此下方移動到一排。 我們嘗試了很多方法來編寫 CSS 以防止這種情況發生並將所有內容保持在一行,包括隱藏整個輪播直到它完成加載。 沒有什麼能提供我們作為用戶訪問商店時希望看到的那種解決方案。
抱歉這麼短的咆哮,但確實,產品和類別輪播是響應式商店中靈活元素的完美風暴:圖像可能不是通用高度,產品名稱可能跨越多行,您可能有也可能沒有標籤。 基本上,它歸結為:行沒有固定的高度是可能的,而且你也不知道寬度。 娛樂時間。
最後,我們決定將所有幻燈片(除了第一個)設置為visibility: hidden
直到輪播完成加載,此時我們向輪播添加一個類以將所有幻燈片更改為再次可見。 這解決了它首先佔用額外高度的問題。
此外,我們最初為非包裝彈性盒中的幻燈片設置了flex-shrink: 0
和flex-base: 340px
。 這使它們位於一條線上,並為幻燈片提供了一個近似的初始寬度。 隨著這個謎題的解決——是的,這聽起來很讓人頭疼——我們添加了一些修復程序來為點和箭頭留出空間。 有了這個,旋轉木馬幾乎沒有 CLS 了!
事後看來是20 ⁄ 20
最後,是幾個月來的許多小改動提高了我們的分數,但我們還沒有完成。 我們主要與兩個人一起進行前端改進,而團隊的其他人則專注於改進後端。 雖然這樣可能會慢一點,但它確保沒有重疊,並且可以清楚地歸因於分數的差異。 一些很有幫助的資源是 Smashing Magazine 上關於該雜誌自身改進的精彩文章。
在某些時候,你應該嘗試的事情變得不明顯,因為你認為它們不應該產生巨大的影響,但之後的某個時候你意識到它們確實如此。 不僅如此,這個項目再次告訴我們的是,從一開始就考慮性能和指標是多麼重要,從設想設計和編碼原型到模板中的實現。 早期被忽視的小事情可能會增加你以後必須爬上才能撤消的大山。
以下是我們學到的一些關鍵方面:
- 優化 JavaScript 不如按需加載有效;
- 優化 CSS 似乎比優化 JavaScript 獲得更多分數;
- 使用 CLS 編寫 CSS 類並牢記關鍵 CSS 的提取;
- 查找 CLS 問題的工具還不完善。 跳出框框思考並檢查幾個工具;
- 評估您集成的每個第三方服務的文件大小和性能時間。 如果可能的話,推遲整合任何會減慢一切的東西;
- 定期重新測試您的頁面以了解 CrUX 更改(尤其是 CLS);
- 定期檢查是否仍需要所有舊支持條目。
我們的改進清單上還有一些東西需要改進:
- 我們在主文件中仍然有很多未使用的 CSS 可以刪除;
- 我們想完全刪除 jQuery。 這將意味著重寫我們的部分代碼,尤其是在結帳區域;
- 需要對如何包含外部滑塊進行更多的實驗;
- 我們的移動點分數可能會更好。 尤其是移動方面需要進一步的工作;
- 所有產品圖片都需要添加響應式圖片;
- 我們將專門檢查內容頁面以了解他們可能需要的改進,尤其是在 CLS 方面;
- 使用 Bootstrap 的折疊插件的元素將被替換為原生 HTML
details
標籤; - DOM 大小需要減小;
- 我們將整合第三方服務以獲得更快更好的搜索結果。 這將伴隨我們需要集成的大量 JavaScript 依賴項;
- 我們將通過查看自動化工具以及自己使用屏幕閱讀器和鍵盤導航運行一些測試來改進可訪問性。
更多資源
- “DevTools 調試技巧和快捷方式(Chrome、Firefox、Edge)”,Vitaly Friedman,Smashing Magazine
- “我最近收藏和閱讀的一些性能博客文章,” Chris Coyier,CSS-Tricks
- “衡量核心網絡生命力的深入指南”,Barry Pollard,Smashing Magazine
- “從語義 CSS 到 Tailwind:重構 Netlify UI 代碼庫”,Netlify 的 Charlie Gerard 和 Leslie Cohn-Wein
- “CSS 審計工具”,Iris Lješnjanin,Smashing Magazine
- “今天你可以用 CSS 做的事情”,Andy Bell,Smashing Magazine
- “如何提高 CSS 性能”,Calibre 的 Milica Mihajlija
- “移動性能不平等差距,2021 年,”亞歷克斯·羅素
- “在 2021 年最大限度地優化 Web 的圖像加載,” Malte Ubl
- “謙虛的
<img>
元素和核心網絡生命力”,Addy Osmani,Smashing Magazine