1. 程式人生 > >常見 Web 性能優化方式

常見 Web 性能優化方式

rev 通用 關系 跳幀 osi 顏色 fonts b2b 一點

這篇文章是我閱讀 Web Performance 101 之後的進行的粗糙的翻譯作為筆記,英語還行的童鞋可以直接看原文。

這篇文章主要介紹了現代 web 加載性能(註意不涉及代碼算法等),學習為什麽加載性能很重要、有哪些優化的方法以及有哪些工具可以幫助我們對網站進行優化。

為什麽性能優化很重要?

技術分享圖片

首先,加載緩慢的網站讓人很不舒服!

最明顯的例子就是當一個移動網站加載太慢的時候,用戶體驗如同觀看一部恐怖電影。

圖片來源:?Luke Wroblewski

技術分享圖片

第二,網站性能直接影響你的產品質量。

—— 2016 年,AliExpress 將他們網站的性能提升了三分之一,然後他們收到的訂單增加了 10.5%!

——2006 年,谷歌曾經嘗試將他們的搜索放慢 0.5 秒然後發現用戶的搜索(請求)次數減少了 25%。

——2008 年,Aberdeen 集團發現將網站放慢 1s,會導致用戶滿意度下降 16%。

此外還有一系列如上的數據,不管是新的還是舊的:(wpostats.com?·?pwastats.com)。

這就是為什麽網站性能很重要。

技術分享圖片

現在,我們需要弄懂當我們說一個網站很快意味著什麽。

在什麽情況下可以說一個網站很快?

——它必須加載很快(文件下載、界面渲染),

——然後,在加載之後,它必須很快的執行(比如動畫不跳幀、滾動很絲滑)。

技術分享圖片

網站加載很快意味著:

——服務器對於客戶端請求響應很快,

——網站自身加載渲染很快。

技術分享圖片

在這篇文章中,我們將會討論這個因素:如何讓網站快速加載以及渲染。

有哪些性能優化方式?

JavaScript

一、壓縮代碼

先從 JavaScript 開始吧。通常情況下,JavaScript 是網站加載緩慢的根源。

技術分享圖片

第一種 JavaScript 優化方式是壓縮,如果你已經知道了的話,直接跳過吧。

什麽是壓縮?在一般情況下,人們寫 JavaScript 代碼會使用一種方便的格式,包含縮進、富有含義的長變量名、寫註釋等等。因為這種方式,代碼具有很高的可讀性,但是多余的空格和註釋會使得 JavaScript 文件變得很大。

技術分享圖片

為了解決這個問題,人們想到了代碼壓縮。在壓縮的過程中,代碼會被去掉所有不必要的字母,替換成短的變量名,去掉註釋等等。在最後,代碼文件變得比之前更小,但是代碼的功能並不受影響。

代碼壓縮可以將代碼文件減小大約 30% ~ 40%。

技術分享圖片

主流的代碼打包工具都支持代碼壓縮:

——?mode: production?in webpack,

——?babel-preset-minify?in Babel,

——?gulp-uglify?in Gulp

二、使用 asyncdefer

技術分享圖片

接下來,你寫了一個 JavaScript 腳本,然後進行了壓縮,現在想要在頁面中加載它。該如何做呢?

技術分享圖片

最簡單的方式就是寫一個 script 標簽,然後 src 屬性指向你所寫腳本的路徑,然後它就可以照常開始工作啦!

但是,你知道這種方法有什麽問題嗎?

技術分享圖片

問題就在於 JavaScript 會阻塞渲染。

技術分享圖片

這是什麽意思?

當你的瀏覽器加載頁面的時候,它會轉換 HTML 文檔成為標簽,然後構建 DOM 樹。隨後它會使用 DOM 樹渲染頁面。

問題在於,JavaScript 代碼可以改變 DOM 樹的構建方式。

技術分享圖片

例如,JavaScript 可以通過 document.write 寫一個 HTML 註釋的起始標簽到文檔中,然後整個 DOM 樹都會被毀掉。

這就是為什麽瀏覽器在碰到 script 標簽的時候會停止渲染頁面,這樣做可以防止 document 做多余的工作。

技術分享圖片

從瀏覽器的角度來看:

——瀏覽器遍歷文檔,然後會解析它

——在某些時刻,瀏覽器遇到了 script 標簽,然後停止了 HTML 轉換,它開始下載並執行那些 script 代碼

——一旦代碼執行完畢,瀏覽器繼續遍歷 HTML 文檔,然後渲染頁面

技術分享圖片

實際上,這意味著當你添加一個 script 標簽到頁面中時,它後面的內容在它下載並執行完畢之前都是不可見的。如果你添加一個 script 到 head 標簽中,所有的內容都會變得不可見——直到 script 被下載執行完畢。

技術分享圖片

那我們該怎麽辦呢?應該使用 asyncdefer 屬性。

這些屬性讓瀏覽器直到 script 腳本可以在後臺下載,不必阻塞文檔渲染,下面是詳細的介紹:

——async 讓瀏覽器異步下載(在後臺)script 代碼,然後繼續解析渲染 HTML。(如果在頁面渲染完畢之前,script 代碼已經下載好了,那麽就先停止渲染,先執行 script 代碼。由於下載所消耗的時間通常大於 HTML 轉化,所以這種情況實際上不多見)。

——defer會告訴瀏覽器在後臺異步下載 script 代碼,直到 HTML 轉化渲染完畢才開始執行這些 script 代碼。

技術分享圖片

這裏有兩大不同點:

——async script 標簽會在下載之後盡快地執行,它們的執行順序沒有規律。這就意味著有 async 屬性的 React bundle script 和 app bundle script 在同一時刻開始下載,由於 app bundle 更小所以會先下載完畢,導致 app 的 bundle script 先執行。然後網站就崩掉了~

——defer 不像 async,會在加載以及文檔渲染完畢之後按照 script 標簽的順序開始執行,因此,defer 是更適合的優化方案。

技術分享圖片

三、代碼切割

技術分享圖片

繼續。

很多時候,應用都是打包到一個 bundle 裏面,然後每次請求都發送到客戶端。但是這樣做的問題在於有些頁面我們見到的場景很少,但是它們的代碼同樣被打包到了我們的 bundle 中,這樣每次頁面加載的代碼多於實際需要,造成了性能浪費。

技術分享圖片

這個問題通常使用代碼切割進行解決,把大的 bundle 切割成一個個小的。

通過代碼切割,我們把不同功能的代碼打包到了不同的文件,只在必要的時候加載必要的代碼。由於使用這樣的做法,用戶再也不會下載他們不需要用到的代碼了。

技術分享圖片

那麽我們怎麽切割代碼呢?

首先,你需要一個代碼打包工具,比如 Webpack、Parcel 或者 Rollup。所有的這幾個工具都支持一個特殊函數 import()

在瀏覽器中,import() 接受傳遞給它的 JS 文件並異步下載該文件。這可以用於加載應用程序一開始不需要但是接下來可能會用到的庫。

技術分享圖片

但是在打包工具中,import() 的功能又有所不同。如果你在代碼中傳遞了一個文件給 import() 並且在之後進行打包,打包工具會把這個文件以及其所有的依賴打包到一個單獨的文件中。app 運行到 import 函數時會單獨下載這個文件。

因此,在上方的例子中,webpack 會把 ChangeAvatarModal.js 及其依賴打包到單獨文件中。在代碼執行到 import 時,這個單獨文件會被下載。

這就是實際的代碼切割。

技術分享圖片

第二,在 React 和 Vuejs 中,會有基於 import() 的工具能夠讓你的代碼切割工作更加輕松。

例如,react-loadable 是一個組件,用於等待其他組件加載,在其他組件加載時,它會進行占位。React 16.6 添加了一個相似的內置功能組件,叫做 Suspense。此外 Vuejs 也已經支持異步組件一段時間了。

技術分享圖片

如果優化得很好的話,我們可以減少很多不必要的數據的下載,代碼切割能夠成為最重要的流量優化工具。

如果你的 app 只能做一種優化的話,那就是代碼切割。

四、移除依賴中的未使用代碼

技術分享圖片

另外一個重要的優化點在於包的依賴。

——例如,momentjs 這個庫,用於進行時間操作,它包含了大約 160 kb 大小的不同語言的文件包。

——React 甚至把 propTypes 包含在生產環境的包中,盡管這不是必要的。

——Lodash,你很有可能引入了整個完整的包,盡管你可能只需要其中的一兩個方法。

上面這些就是把不必要的代碼引入打包的情況。

技術分享圖片

為了幫助開發者移除多余的代碼,作者和谷歌一起維護了一個 repo 收集關於如何在 webpack 中優化你的依賴,使用這些建議可以讓你的 app 更快更輕巧!

→?GoogleChromeLabs/webpack-libs-optimizations

五、總結

技術分享圖片

以上都是 JavaScript 的優化方式,總結起來就是:

——壓縮你的 js 代碼

——使用 asyncdefer 加載 script

——切割你的代碼,讓應用只加載必須的代碼

——移除依賴中實際未使用的代碼

CSS

接下來是如何優化 css 代碼。

技術分享圖片

一、壓縮 CSS 代碼

首先,壓縮 CSS,就像 JavaScript 代碼一樣。刪除不必要的空格和字母來使你的代碼更小。

技術分享圖片

這些工具可以幫助你壓縮 CSS 代碼:

—— webpack’s?postcss-loader?with?cssnano

—— PostCSS’s?cssnano

—— Gulp’s?gulp-clean-css

二、提取 Critical CSS

技術分享圖片

第二、styles 阻塞渲染,就像之前 script 那樣。

技術分享圖片

因為沒有樣式的網站看起來很奇怪。

如果瀏覽器在樣式加載之前渲染頁面,那麽用戶就會看到上面那樣的情況。

技術分享圖片

然後頁面就會閃爍,然後就會看到上面截圖這樣子,很難說是一種好的用戶體驗。

技術分享圖片

這就是為什麽樣式加載的時候頁面會是空白的。

現在有一種比較機智的優化方式。瀏覽器在加載樣式之前保持空白頁是很有理由的,我們不必從這一點下手。但是我們仍然可以想辦法讓頁面渲染更快——讓頁面只加載渲染初始界面所必要的樣式,剩余的樣式在之後加載,這些渲染初始界面所必要的樣式稱為“Critical CSS”。

讓我們看看是怎麽做的。

技術分享圖片

1、把頁面樣式分為 critical 的和 non-critical 的。

2、把 critical CSS 嵌入到 HTML,真能夠讓它們盡快地被加載。

技術分享圖片

現在,當你加載頁面的時候,頁面能夠很快地被渲染,但是你仍然得加載那些不重要的 CSS。

有多種方式可以加載剩余的 CSS,下面的方式是我所傾向的:

3、使用<link rel="preload"> 獲取非必要的 CSS。

4、一旦文件被加載到緩存以後,把 rel 屬性從 preload 切換為 stylesheet。這可以讓瀏覽器從緩存中獲取 CSS 並應用到頁面中

技術分享圖片

那我們怎麽知道哪些 CSS 是必須的,哪些 CSS 是不必須的呢?通常情況下,規則如下:

移除 CSS 樣式知道頁面看起來變得滑稽,那麽剩下的 CSS 就是必要的。

例如,頁面的布局樣式或者文章的文本樣式是必須的,因為缺少它們會使得頁面看起來很爛。而 JavaScript 彈出窗或者頁腳的樣式是非必須的,因為用戶不會在一開始就看到它們,缺少那些樣式,頁面看起來仍然十分完美。

技術分享圖片

聽起來可能比較復雜,但是有很多自動化工具可以幫助我們完成這項工作。

——?styled-components. It’s a CSS-in-JS library that extracts and returns critical styles during server-side rendering. It works only if you already write styles using?styled-components, but if you do, it works really well.

——critical. It’s a utility that takes an HTML page, renders it in a headless browser and extracts styles for above-the-fold content. Because?critical?runs only over a single page, it might not work well for complex single-page apps.

——?penthouse. It’s similar to?critical?but works with URLs instead of HTML pages.

技術分享圖片

這種做法一般可以節約 200 ~ 500 ms 左右的首屏渲染時間。

了解更多 Critical CSS 的知識,閱讀?the amazing Smashing Magazine’s guide.

三、總結

技術分享圖片

這就是 CSS 優化的主要策略,總結起來就是:

——壓縮 CSS 代碼

——提取必要的 CSS,讓頁面首先加載它們

HTTP

現在讓我們看看 HTTP 的優化。

技術分享圖片

一、壓縮代碼

讓 HTTP 傳輸較少數據的方式仍然是壓縮代碼,本節主要說壓縮 HTML 代碼,JS、CSS 的代碼壓縮在之前已經講過了。

二、GZIP 壓縮

技術分享圖片

壓縮代碼的第二種方式是 GZIP 壓縮。

Gzip 是一種算法,它可以使用復雜的歸檔算法壓縮你發送到客戶端的數據。在壓縮之後,你的文件看起來像是無法打開的二進制文件,但是它們的體積會減小 60% 到 80%。瀏覽器接受這些文件之後會自動進行解壓縮。

技術分享圖片

基本上,使用 Gzip 已經是生產環境的標準,因此如果你使用一些流行的服務器軟件比如 Apache 或者 Nginx,你就可以修改配置文件開啟 Gzip 壓縮。

Apache instructions?·?Nginx instructions

註意:

使用這些說明啟用 Gzip 將會導致服務器動態壓縮資源,這會增加服務器響應時間。在大多數情況下你不需要關心這一點,但如果你希望提高響應時間,可以在構建的時候進行資源預壓縮。

技術分享圖片

註意:

不要對文本文件之外的文件進行 Gzip 壓縮!

圖像、字體、視頻或者其他二進制文件通常已經被壓縮過了,因此對它們進行 Gzip 壓縮只會延長響應時間。SVG 圖片是唯一的例外,因為它也是文本。

三、Brotli 壓縮

技術分享圖片

Gzip 有一個替代品,一種叫 Brotli 的算法。

__Brotli 的優點:__同樣的 CPU 載荷下,它壓縮效率比 Gzip 高 20% 到 30%。就是說可以減少 30% 下載量!

__Brotli 的缺點:__它很年輕,瀏覽器以及服務器的支持度還不夠,所以你不能用它來替代 Gzip。但是可以針對不同的瀏覽器使用 Gzip 或者 Brotli。

技術分享圖片

Apache 從 2.4.26 開始支持 Brotli,Nginx 有外部模塊支持 Brotli。

Apache instructions?·?Nginx module

註意:

不要把 Brotli 的壓縮等級設置到最大,那樣會讓它壓縮得比 Gzip 慢。設置為 4 是最好的,可以讓 Brotli 壓縮得比 Gzip 更小更快。

四、CDN

技術分享圖片

現在,我們聊聊 CDN。

什麽是 CDN?假設你在美國假設了一個應用。如果你的用戶來自華沙,他們的請求不得不從波蘭發出,一路顛簸來到美國,然後又得回到波蘭。這個請求過程將會消耗很多時間:

——網絡請求要跨越很長的一段距離

——網絡請求要經過很多路由或者類似設備(每個設備都有一段處理時間)

如果用戶想要獲取 app 數據,而且只有美國的服務器知道如何處理數據,那上面這些過程好像都是必要的。但對於靜態內容而言,上面的請求過程完全沒有必要,因為它們請求的只是一些靜態內容,完全可以部署到任何服務器上。

技術分享圖片

CDN 服務就是用來解決這個問題的。CDN 代表“Content Delivery Network(靜態內容分發)”,CDN 服務在全世界提供許多服務器來 “serve” 靜態文件。如果要使用的話,只需要在一個 CDN 服務註冊,然後上傳你的靜態文件,然後更新 app 中引用的文件的地址,然後每個用戶都會引用離他們最近的服務器上的靜態文件了。

根據我們的經驗,CDN 基本上能把每個請求的延遲從上百毫秒減少到 5-10 毫秒。考慮到當頁面打開時有很多資源要加載,CDN 的優化效果是很驚人的。

五、資源預加載

技術分享圖片

你知道嗎?谷歌在你開始點擊搜索之前已經在加載搜索結果的第一項了。這是因為三分之一的用戶會首先點擊第一個搜索結果,預加載內容可以讓用戶更快的看到目標頁面。

如果你確定你的頁面或者資源會在不久之後被用到,瀏覽器允許你進行預加載。

技術分享圖片

有五種方法可以實現預加載,它們每一種的適用場景都不同:

——<link rel="dns-prefetch"> 提示瀏覽器對一個 IP 地址提前進行 DNS 請求。這對於 CDN 請求很有用,此外一些你知道域名但是不知道具體地址的資源的預加載也可以使用。

——<link rel="preconnect"> 提示瀏覽器提前連接到某臺服務器。在 dns-prefetch 適用的場景同樣適用,但它可以建立完整的連接並節約很多時間。缺點是打開新的連接很消耗資源,因此不要過度使用。

——<link rel="prefetch"> 會在後臺對資源進行低優先級預加載然後緩存,這個比較有用,比如在進入 SPA 的下一個頁面之前加載 bundle。

——<link rel="preload"> 會在後臺對資源進行高優先級的預加載。這對於加載短時間內即將用到的資源而言比較有用。

——<link rel="prerender"> 會在後臺預加載特定頁面,然後在不可見的 tab 中渲染頁面。當用戶進入這個頁面時,頁面可以立馬呈現在用戶面前。這是谷歌用於預加載第一條搜索結果的方案。

註意:

不要過度使用預加載,雖然預加載能夠提升用戶體驗、加速應用,但是會導致不必要的流量消耗;尤其是在移動端,用戶會消耗過多的不要的流量,這同樣會降低用戶體驗。

閱讀更多:Preload, prefetch and priorities in Chrome?·?Prefetching, preloading, prebrowsing

六、總結

技術分享圖片

HTTP 優化方式:

——?壓縮 HTML 代碼,就像其它資源那樣

—— 使用?Gzip?and?Brotli 壓縮文本資源

—— 使用 CDN 節省靜態資源的下載時間

—— 預加載一會將要用到的資源

圖片

技術分享圖片

繼續,說說圖片優化。

一、合適的格式

技術分享圖片

圖片消耗了大量的流量,但慶幸的是圖片加載不阻塞渲染。但圖片優化仍然是必要的,我們需要讓圖片加載更快、消耗更少的流量。

第一,也是最重要的一點,選擇合適的圖片格式。

最常見的圖片格式是:svgjpgpngwebpgif

技術分享圖片

svg 最適合矢量圖,比如 icon 和 logo。

技術分享圖片

jpg 最適合照片,因為它壓縮圖片時質量損耗最小,以至於肉眼難以發現。

技術分享圖片

png 適合沒有任何質量損失的光柵圖形 - 例如光柵圖標或像素藝術。

技術分享圖片

webp 最適合照片或者光柵圖片,因為它支持有損或者無損壓縮。它的壓縮比也比 jpgpng 更優秀。

不幸的是 webp 只能在 chrome 使用,但是你仍然可以使用 jpgpng 來實現一個 fallback。

技術分享圖片

上面就是具體實現。

這樣寫的話,支持 webp 的瀏覽器會加載 webp 格式的圖片,不支持 webp 格式的瀏覽器會加載 jpg 最為備用方案。

技術分享圖片

最後是 gif

不要使用 gif,它非常笨重。超過 1M 的 gif 最好使用視頻文件代替,可以更好的壓縮內容。

See also:?Replace Animated GIFs with Video?at WebFundamentals

二、圖片壓縮

技術分享圖片

除了使用合適的圖片格式以外,圖片壓縮也可以是優化方案。下面是幾種圖片壓縮方式:

技術分享圖片

首先是 svg

——壓縮。因為 svg 圖片是文本,所以可以移除空格和註釋

——簡化 path,如果 svg 是自動工具生成的,其內部的 path 可能會很復雜,這種情況下,移除那些不影響 svg 樣式的 path

——簡化 svg 文件結構,如果 svg 是自動工具生成的,通常會包含很多多余的 meta 元素,移除它們可以減小文件體積

這些優化方式都可以直接使用 svgo 實現,它還有 UI 界面:a great UI for svgo

技術分享圖片

第二個:jpg

——減小圖片維度。根據我的經驗,這是一個開發人員使用 jpg 常犯的錯誤

技術分享圖片

這種情況常發生於我們把一張大尺寸的圖片塞進一個小尺寸的容器中時。比如我們把一張 2560 * 1440 px 的圖片放到一個 533 * 300 px 的容器中。

當這種情況發生時,瀏覽器會加載過大的文件,然後還要花時間縮小圖片,知道能夠塞進去那個小小的容器,這些都是無用功。

要解決這個問題,可以直接在你的 PS 或者其他工具中對圖片進行編輯;或者你也可以使用 webpack loader(比如 responsive-loader)。如果要使用大尺寸圖片適配高分屏,可以通過 <picture> 或者 <img srcset> 代替。

技術分享圖片

還可以對 jpg 進行圖片降維壓縮,圖片質量壓縮到原來的 70 ~ 80,圖片壓縮導致的質量損失會很難發現。

技術分享圖片

技術分享圖片

上面可以看出壓縮後圖片質量損失不大。

技術分享圖片

但是我們可以看到圖片的大小減小了很多。這就是為什麽推薦對 jpg 圖片進行 70-80 水平的壓縮,因為圖片信息損失很小,但是體積壓縮很大。

技術分享圖片

除了以上方式外,我們還可以使用漸進式圖片。

技術分享圖片

上方是非漸進式圖片加載的方法。

技術分享圖片

這是一張漸進式的圖片的加載方式。

可以通過 PS 或者 Gimp 制作漸進式圖片。也可以使用 webpack-loader(比如 image-webpack-loader)或者其他工具。

註意:

漸進式圖片可能比常規圖片更大,而且解碼更慢。

技術分享圖片

第三,png

——使用隔行掃描 PNG。 隔行掃描 PNG 的工作方式與漸進式 JPEG 相同:它從低質量開始渲染,但在加載時進行改進。 但它不是適合所有場景。例如,逐步加載 PNG 圖標看起來很奇怪 - 但它可能適用於其他某些圖像。

——使用索引顏色。 通過使用索引顏色,PNG 圖片將其所有顏色放入調色板中並使用它來引用每種顏色。 這使得每個像素所需的字節數更小,並且可能有助於降低整體圖像權重。 由於調色板大小有限(最多256種顏色),因此此解決方案不適用於具有大量顏色的圖像。

這兩種方式都可以通過圖片編輯器或者 image-webpack-loader 或者其他工具實現。

技術分享圖片

以上的所有優化都可以使用自動化工具完成,之前都已經提到過,但是這裏再總結一下:

— webpack has image-webpack-loader which runs on every build and does pretty much every optimization from above. Its default settings are OK

— For you need to optimize an image once and forever, there’re apps like ImageOptim and sites like TinyPNG.

— If you can’t plug a webpack loader into your build process, there’re also a number of CDNs and services that host and optimize images for you (e.g., Akamai, Cloudinary, or imgix).

三、總結

技術分享圖片

圖片優化總結:

——選擇合適的圖片格式

——通過圖片降維、質量壓縮或者使用漸進式圖片優化圖片加載時間

字體

技術分享圖片

最後一個優化方式就是字體了。

有時候頁面加載好了,所有的樣式、布局都已經可見了,但是字體還沒有出現或者顯示異常,這就是字體問題所導致的,自定義字體尚未下載完畢,這個時候瀏覽器會等待幾秒,如果仍然未下載,瀏覽器才會使用備用字體作為替代。

這種行為在某種程度上避免了字體的閃爍,但是在緩慢的網絡條件下,這種行為使得頁面加載變得緩慢。

一、指定 fallback 字體

我們需要了解一下如何優化這種情況。

技術分享圖片

首先,要記得設置 fallback 字體。

fallback 字體會在自定義字體無法下載或者下載時間過長時被使用。它在 CSS 的 font 或者 font-family 的第一個指定字體後面指定,比如上方的Arial, sans-serif

fallback 字體應當是比較流行的內置字體(比如 Georgia);也可以是比較通用的字體系列(如 serif 或者 sans-serif);通常情況下,即使你指定了內置的字體作為 fallback,但是你仍然需要添加一個通用的字體系列——因為內置字體可能也會在某些設備上缺失。

技術分享圖片

沒有 fallback 字體的話,一旦自定義字體缺失,瀏覽器會使用默認的 serif font 進行渲染。這樣可能會導致頁面比較難看。

技術分享圖片

使用 fallback 字體,至少你有機會定義一個和你的自定義字體相近的字體作為備用方案。

二、使用 font-display

技術分享圖片

第二點優化,使用 CSS 的 font-display 屬性指定自定義字體。

font-display 屬性會調整自定義字體的應用方式。默認情況下,它會設置為 auto,在大部分主流瀏覽器中,意味著瀏覽器會等待自定義字體加載 3s。這意味著如果網絡太慢的話,用戶需要等待 3s 後字體才會顯示。

這很不好,為了優化這一點,指定 font-display

Note: in Microsoft Edge, the?font-display: auto?behavior is different. With it, if the custom font is not cached, Edge immediately renders the text in the fallback font and substitutes the custom font later when it’s loaded. This is not a bug because?font-display: auto?lets browsers define the loading strategy.

技術分享圖片

有兩個 font-display 的值我認為比較適用於大部分情況。

第一個是 font-display: fallback。這樣指定的話,瀏覽器會使用最早能夠獲得的字體立即渲染,不管是已經緩存的自定義字體還是 fallback 字體。如果自定義字體沒有被緩存的話,瀏覽器會下載它。如果下載得足夠快(通常是 3s 內),瀏覽器會使用自定義字體替換 fallback 字體。

這種情況下,用戶可能會在讀 fallback 字體的文本時,瀏覽器突然進行字體替換,這對於用戶體驗而言並不是很差,總比不顯示任何字體要強。

技術分享圖片

第二個適用的 font-display 值是 optional。使用這個值,瀏覽器同樣會立即使用可獲得的字體進行文本渲染:不管是已緩存的自定義字體還是 fallback 字體。但是當自定義字體未緩存時,在下載好自定義字體後,瀏覽器不會立即替換已有的 fallback 字體,直到頁面下一次刷新。

這種行為意味著用戶始終只會看到一種字體,不會出現字體替換的情況。

技術分享圖片

那我們該如何選擇這兩個值呢?

我相信這是一個品味問題。 我個人更喜歡用自定義字體展示文本,因此我選擇 font-display:fallback 值。 如果你覺得訪問者第一次訪問時看到 fallback 字體的頁面沒有什麽關系,那麽 font-display:optional 對您來說非常有用。

Note: this?font-display?trick is not applicable to icon fonts. In icon fonts, each icon is usually encoded by a rarely used Unicode character. Using?font-display?to render icons with a fallback font will make random characters appear in their place.

三、總結

技術分享圖片

字體優化方案的總結:

—— 指定合適的 fallback(備用)字體?(還有通用的字體系列)

——?使用?font-display?來配置自定義字體的應用方式。

有哪些可用的優化工具

技術分享圖片

最後是一些有助於頁面性能優化的工具。

技術分享圖片

第一個是 Google PageSpeed Insights。

技術分享圖片

第二個是 Lighthouse。

技術分享圖片

第三個是 WebPageTest。

最後一個是 webpack 插件:webpack-bundle-analyzer。

具體的介紹就沒寫了,點進去直接用就知道啦。

感謝閱讀!

原作者推特:@iamakulov。

Thanks to?Arun,?Anton Korzunov,?Matthew Holloway,?Bradley Few,?Brian Rosamilia,Rafael Keramidas,?Viktor Karpov, and Artem Miroshnyk (in no particular order) for providing feedback on drafts.

譯者水平有限,難免存在紕漏,敬請各位斧正。

常見 Web 性能優化方式