摘要:簡言之,我們認為好的用戶體驗從快速的內容傳輸開始,也就意味著性能美觀。每一步我們都在探討如何在獲得好的用戶體驗和保證設計美感的同時,最小化對性能的影響。字型子集設定到目前為止,子集設定是改善網頁字體性能最快的方式。
作者 Declan
原文鏈接
最近更新了我們的網站,它是經過了設計上的全面驗收的。但實際上,作為軟件開發者,我們會注重很多技術相關的零碎的東西。我們的目標是控制性能,注重性能,未來可伸展,為網站增添內容是一種樂趣。接著就來告訴你,為什么我們的網站速度比你們的快吧(抱歉,確實是這樣的)。
性能設計在我們的項目中,我們每天都會和設計師和產品負責人討論關于平衡美觀和性能的問題。對于我們自己的網站,這樣做是很簡單的。簡言之,我們認為好的用戶體驗從快速的內容傳輸開始,也就意味著 性能 > 美觀。
好的內容、布局、圖片和交互是吸引用戶的重要因素。這每個因素都會影響頁面的加載時間和終端用戶體驗。每一步我們都在探討如何在獲得好的用戶體驗和保證設計美感的同時,最小化對性能的影響。
內容優先我們想要把核心內容盡快地呈現給用戶,意味著我們要處理好基本的 HTML 和 CSS。每個頁面都應該達到基本的目的:傳遞信息。JS、CSS、網頁字體、圖片、網站分析等優化都是位居于核心內容之下的。
可控性給理想網站定義了標準后,我們總結出:要想達到預期效果,就要能對網站各方面的控制都游刃有余。我們選擇構建自己的靜態站點生成器,包括資源傳輸,并且由我們自己操控。
靜態站點生成器我們用 Node.js 實現了靜態站點生成器。它是采用帶有簡短 JSON 頁面描述標簽的 Markdown 文件來生成整個網站結構和它所有的資源。為了包括特殊的頁面腳本,也可以附帶一個 HTML 文件。以下是一個簡單化的描述標簽和 markdown 文件,用于博客的發布,用它來生成真正的 HTML。
JSON 描述標簽:
{ "keywords": ["performance", "critical rendering path", "static site", "..."], "publishDate": "2016-07-13", "authors": ["Declan"] }
markdown 文件:
# Why our website is faster than yours We"ve recently updated our site. Yes, it has a complete... ## Design for performance In our projects we have daily discussions...圖片傳輸
平均一個 2406kb 的網頁中 1535kb 是圖片。就因為圖片在網站中占據了這么大的一個比例,所以它也是性能優化的重點之一。
WebP格式WebP是一種現代圖片格式,為網頁圖片提供了出色的低損耗、有損壓縮。WebP格式的圖片實質上比其它格式的小,有時可以比同樣的 JPEG 圖片小 25%。 WebP被大多數人所忽略,也沒被經常使用。截止到寫這篇文章的時候,WebP 僅支持Chrome, Opera 和 Android (仍超過了我們50%的用戶),但我們可以優雅降級為 JPG/PNG。
使用 元素我們可以把圖片從 WebP 優雅地降級到其它被廣泛支持的圖片格式,如JPEG:
我們使用Scott Jehl 的 picturefill 來使那些不支持 元素的瀏覽器獲得支持,在各個瀏覽器中達到一致的效果
我們使用 作為那些不支持 或者 JS 的瀏覽器的后備元素。使用圖片的最大實例確保了它在后備方案中的可行性。
生成盡管圖片傳輸方式已經確定了,我們仍需要思考該怎樣有效地執行。我喜歡 元素的功能,但不喜歡寫上面那些代碼段,尤其是寫內容時必須把它加進去。我們不想做這么費力的事情:每張圖片都要寫 6 個實例,所以優化這些圖片并且把它們寫在markdown文件的 里面。所以:
生成圖片在構建過程中,原圖片的多個實例,包括JPG, PNG和WebP格式,我們使用 gulp responsive 來生成。
最小化圖片 在markdown文件中寫[圖片描述](image.jpg).在構建過程中使用自定義Markdown渲染器來為已經完全成熟的 元素編譯傳統的markdown圖片聲明。
SVG動畫我們為自己的網站選擇了特定的圖標類型,其中SVG插圖占了主要地位。這樣做有以下幾個原因:
首先,SVG的圖片比位圖更??;
其二,SVG圖片本身就是響應式的,有很棒的伸縮性, 所以不需要圖片生成及 元素;
最后也是很重要的一點,就是我們可以通過CSS來不斷改變它,賦予它新的活力!我們所有的組合頁面都有一個自定義的動態SVG圖, 可以被概述頁面所復用。這張圖片作為我們所有組合頁面的一種循環風格,使得頁面設計一體化,同時又幾乎不會對性能造成影響。請看這張動畫,看看我們是如何用CSS來改變它的。
自定義網頁字體在深入之前,這里有一個關于在瀏覽器設置自定義字體的簡短介紹。當瀏覽器發現CSS里面有@font-face 的定義,但是用戶的電腦并不支持該字體時,它會嘗試下載該字體文件。在下載時,多數瀏覽器根本不會用這種字體來展示文本。這種現象稱為“不可見文本的閃現” 或者 FOIT。如果你有留意,你會發現網頁上都有這種情況存在。如果你問我,我會告訴你這會影響用戶體驗。它延遲了用戶讀取他們所需內容的時間。我們可以迫使瀏覽器改變這種行為,變成 “無樣式內容閃現” 或者稱為 FOUT。我們告訴瀏覽器先使用普通字體,像 Arial 或者 Georgia。當自定義的字體下載完成后,再代替標準字體并且重新渲染。這樣,即使自定義字體下載失敗,仍然不會影響內容的可讀性。然而,有人會認為這是一種妥協的做法,但我們認為自定義字體只是一種優化。盡管沒有自定義字體,網頁看起來也完好,也能百分百的正常運行。勾選/不勾選復選框來切換我們的網頁字體,來自己體驗一下:
切換下載的字體類
使用自定義網頁字體可以改善我們的用戶體驗,只要你能夠優化他們,并且負責任地為之服務。
到目前為止,子集設定是改善網頁字體性能最快的方式。我將會向每個使用自定義字體的網頁開發者推薦它。如果你能完全控制網頁內容,并且知道它將要展示哪些特性的話,你可以完全使用子集設定。但是,即使是僅僅把字體設為西方語言,也會對文件大小造成很大的影響。例如,我們的 Noto Regular WOFF 字體,默認是246KB,將其設為西方語言后,大小下降到31KB。我們使用 Font squirrel webfont, 這種字體真的很易用。
字體監聽器Bram Stein 推出的字體監聽器是一個很了不起的腳本,可以幫助檢查字體是否已被加載。至于你是如何加載字體的,是通過一個網頁字體服務,還是自己上傳就不可知了。在這個監聽器告訴我們所有自定義的字體已經下載完畢后,我們就可以在 元素上添加一個字體加載完畢的類,我們的頁面就會重新用新的字體:
html { font-family: Georgia, serif; } html.fonts-loaded { font-family: Noto, Georgia, serif; }
注意: 為了簡短,我沒有給上面CSS中的 Noto 加上 @font-face 的聲明。
我們可以設定一個cookie來記住所有的字體已經被加載過,就可以讓他們緩存在瀏覽器里面了。我們使用這個cookie來做重復的瀏覽,這個我后續會解釋。
在不久的將來,我們或許不需要 Bram Stein 的腳本來監聽這個行為。CSS開發團隊已經提案一個新的 @font-face 描述器,也叫 font-display。它的屬性值控制著一個可下載的字體是如何在還沒加載出來時就渲染頁面的。這是CSS對font-display的描述:它將帶給我們像上面方法一樣的行為效果。你可以讀讀更多關于 font-display 的屬性。
JS和CSS懶加載一般來講,我們都是盡可能快的加載需要的資源。我們移除一些堵塞的請求來加快頁面渲染,優化首屏,用瀏覽器緩存來處理重復的頁面。
JS懶加載設計上,我們的網站并沒有很多JS。我們發展了一個JavaScript工作流來處理我們目前已有的js, 以及未來會用到的js資源。
JS在 塊里面渲染,這是我們想要的。JS應該只是用來提高用戶體驗,不應該是訪問者需要的關鍵。處理JS堵塞渲染的簡單方法就是把腳本放在頁面的尾部。這樣網頁就會在整個HTML 渲染完畢后才去加載JS。
另一種可以把腳本放在 head 執行的方案是在 標簽里面添加 defer 屬性,來延遲腳本的執行。由于瀏覽器下載腳本是很快的,不會堵塞頁面渲染進程,等到頁面完全加載完,才會執行腳本里面的代碼。還有一件事,我們沒有使用像jQuery這些庫,所以我們的腳本取決于 vanilla 腳本的特性。我們只是想要在瀏覽器加載腳本來支持這些特性。最終的結果就像下面的代碼這樣:
"); }
我們把這小段腳本放在頁面頭部,來檢測瀏覽器是否支持原生JavaScript的 document.querySelector 和 window.addEventListener 屬性。如果支持,我們通過 標簽直接給頁面加載腳本,并使用 defer 屬性讓它不會堵塞頁面渲染。
懶加載CSS對于首屏來講,網站最大的渲染堵塞資源就是CSS了。只有當 里面的CSS文件完全加載完畢時,瀏覽器才會開始渲染頁面。這種做法是經過深思熟慮的,若不是這樣,瀏覽器就需要在整個渲染過程中不斷重新計算布局尺寸,不斷重繪。
為了防止CSS堵塞渲染,我們就需要異步加載CSS文件。我們使用了 Filament Group 的 awesome loadCSS 函數。該函數提供了一個回調,當CSS文件加載完后,我們設置一個cookie來聲明CSS文件已經加載了。我們使用這個cookie來重現頁面,這一點我后續會解釋到。
CSS異步加載也帶來這樣一個問題,盡管 HTML 真的很快被渲染出來,但看起來就只有純粹的HTML,只有等到整個CSS文件加載完且停止時,才會有樣式。這時就要提到關鍵CSS了。
關鍵CSS關鍵CSS就是阻塞瀏覽器渲染出用戶可識別的網頁的一小部分CSS。我們注意網頁的 上半版版面。很明顯,兩個設備的版面的位置有很大的區別。因此,我們做了一個大膽的猜測。
手動地檢測這部分關鍵性的CSS是個很耗時的過程,尤其是樣式、特性等不斷改變時。這里有幾個好的腳本,可以在你構建網頁時,生成關鍵性CSS。我們采用了 Addy Osmani 的版本。
下面是我們分別用關鍵性CSS和整份CSS分別渲染的頁面效果。注意到下半版仍然有部分內容還沒有樣式。
左側網頁是用關鍵CSS渲染的,而右側網頁則是用整份的CSS。紅線是分界線。
服務端我們自己部署 de Voorhoede 網站,因為我們希望能夠控制服務器環境。我們也想要嘗試,是否可以通過改變服務端的配置來大大提升性能。當前我們使用了 Apache 服務和 HTTPS 協議。
配置為了提升性能和安全性,我們研究了如何配置服務端。
我們使用 H5BP apache樣板配置,這個對于改善Apache網絡服務的性能和安全性是個很好的開始。他們也有其他服務器環境的配置。對于我們的大部分 HTML、CSS 和 JS,我們使用GZIP壓縮。對于我們的所有網站資源,都使用緩存HTTP標頭的做法。有興趣請閱讀文件層級緩存的章節。
HTTPS用HTTPS來服務你的網站會對性能造成影響。這主要是設置了SSL握手,引入了大量潛在的東西。但通常情況下,我們可以做一些改變!
HTTP Strict Transport Security 是一個HTTP標頭,可以讓服務器告訴瀏覽器只能用HTTPS來與它交互。這種方式防止HTTP請求被重定向為HTTPS。所有嘗試用HTTP來訪問站點的請求都會被自動轉換成HTTPS。這樣就節省了一個來回。
TLS false start 允許客戶端在第一個TLS回合結束后,馬上向后端發送加密的數據。這種優化為一個新的TLS連接減少了握手次數。一旦客戶端知道了密鑰,就可以開始傳輸應用數據。剩下的握手用來確認是否有人篡改了握手記錄,并且可以并行處理。
TLS session resumption 通過確認瀏覽器和服務器是否已經取得聯系來幫我們節省一個來回。瀏覽器會記住這一次的標識符,下次發起連接時,這個標識符就會被重用,節省了一個來回。
我聽起來像是一個搞開發和運維的,但確實不是。我只是讀過一些書,看過一些視頻。我喜歡 Google I/O 2016 的 Mythbusting HTTPS:Emily Stark 的安全性都市傳奇。
cookies的使用我們沒有用一門服務端的語言,只有靜態的 Apache 網絡服務。但一個 Apache 網絡服務仍可以做包括SSI在內的后端服務,并且讀取cookies。通過巧用cookies和運行那部分被Apache改寫的HTML,我們可以大大提升前端性能。下面這個例子就是了(我們實際的代碼比這個復雜點,但是思想上是一致的):
Apache 服務端邏輯看起來像一行一行的備注,一般以 如果是true的話,我們就假定這是用戶的第一次瀏覽。
第一次瀏覽我們添加了 標簽,里面放置了 。之所以這樣做,是因為我們要異步加載整份CSS和JS。如果JS不能用的話,這種做法是不能執行的。這意味著,我們要用常規的加載CSS的方法來做回退。
我們添加了一個行內的腳本來懶加載CSS,onloadCSS 回調里面可以設置cookies.
在同一份腳本里面,我們異步加載了整份CSS。
在 onloadCSS的回調里面,我們用版本號來設置cookie的值。
在這個腳本后面,我們添加了一行關鍵CSS的樣式。這個會阻塞渲染,但時間是非常短的,而且可以避免頁面展示出來只有純粹的HTML而沒有樣式的情況。
聲明(意味著 css-loaded 的cookie 已經存在)用戶重復瀏覽。因為我們可以從某種程度上來假定,CSS文件之前已經被加載過了,我們可以利用瀏覽器緩存來提供樣式表。這樣從緩存里面加載速度就很快了。同樣的方法也被用來在第一次異步加載字體,后續的重復瀏覽也是從緩存里面獲取字體。
這就是我們第一次和重復瀏覽時,我們用來區分的cookies。
文件級緩存由于我們在重現頁面時很大程度上依賴于瀏覽器緩存,所以我們需要確認我們的緩存是否合理。理想中我們是要永遠的存儲資源(CSS、js、 字體、圖片),只有當這些文件被修改時才需要更新。當請求的URL是唯一時,緩存就會失效。每更新一個版本,我們都會用 git tag 打個標簽。所以最簡單的方式就是給我們請求的URL加上一個參數(代碼版本號),如 https://www.voorhoede.nl/assets/css/main-8af99277a6.css?v=1.0.4.。
但是,這種做法的缺點就是當我們要寫一個新的博客post(這也是我們代碼庫的一部分,并沒有永久地存儲在CMS),原來緩存的資源將會失效,盡管沒有改變原來那些資源。
就在我們嘗試去改善這種方法時,我們發現了 gulp-rev 和 gulp-rev-replace 。這些腳本會自動合理地在我們的文件名稱后面添加一竄hash值。這意味著只有實際上文件被改變時,才會去改變請求的URL,這樣每個文件的緩存就會自動失效。這種做法讓我興奮不已?。?/p> 結果
如果你看到這里,你應該是想要知道結果的。測試網頁的性能可以采用像 PageSpeed Insights 這樣的工具,它有很實用的提示。也可以使用 WebPagetest來測試,有擴展性的網絡分析。我認為測試網頁渲染性能的最好方法就是在瘋狂地遏制網絡通信時來觀察網頁的進程。這意味著,用一種不切實際的方法來遏制通信。在谷歌瀏覽器,你可以這樣操作 (via the inspector > Network tab) 來限制通信,觀察網頁形成過程中,請求是如何緩慢加載的。
下面是我們的網頁在 50KB/s 的情況下的加載狀況。
這是 de Voorhoede site 首屏的網絡分析,是網頁第一次進程的一個概覽。
注意到在50KB/s的網速中,我們是如何讓首屏的渲染只用了 2.27 秒的。也就是第一張幻燈片和瀑布圖里面的黃色線所代表的位置。黃線恰好繪在就是HTML已經加載完的時間位置。HTML包含了關鍵CSS,保證頁面的可觀性。所有其他的CSS都是用懶加載,所以我們可以等到全部資源加載完時才與頁面進行交互。這也是我們想要的效果!
另一個值得注意的就是自定義字體從來不在這緩慢的鏈接上加載。 font face 觀察器會自動注意到這一點。但是,如果我們不異步加載字體,你注視大多數瀏覽器,都會出現 FOIT(不可見文本的閃現,上文有提及)的情況。
所有的CSS文件僅在8s后就都加載完畢。相反,如果我們不采用加載關鍵CSS的方式,而是采用加載全部CSS,我們在前8秒看到的將會是空白的頁面。
如果你感到好奇,想與那些不太注重性能的網站對比一下加載時間,那趕緊試試吧。那個時間肯定是飛漲啊!
用上面介紹的工具測試了我們的網站,結果也是讓人滿意的。 PageSpeed insights 在移動性能方面給了我們100分,多么了不起??!
PageSpeed insights 對 voorhoede.nl的測試結果! 速度100分!
當我們查看 WebPagetest 時,我們得到下面這樣的結果:
WebPagetest 對 voorhoede.nl的檢測結果
可以看出,我們的服務器運行良好,首屏的速度指標是693。 這意味著我們的頁面在693毫秒后就可以在寬屏纜線下被使用了。
技術路線我們這樣還不算完成,還會不斷地重復我們的方法。我不久的將來,我們會主要關注以下內容:
HTTP/2目前我們正在試驗HTTP/2。本文所描述的大多數東西都是基于 HTTP/1.1 權限內的最好實踐。簡言之,HTTP/1.1 要追述到1999年,那時 table布局和行內樣式都如火如荼。HTTP/1.1 從沒為 2.6MB的網頁要接受200個請求而設計。為了減輕舊版協議帶來的痛楚,我們結合JS、CSS、關鍵性CSS,還為小圖片設置數據源URI等。用各種方法來節省請求。自從 HTTP/2 可以在同一個TCP鏈接上平行地運行多個請求后,所有的這些聯結使用和減少請求的做法都可能成為反面模式了。當我們跑完這個實驗后,我們將會采用 HTTP/2 協議。
Service Workers這是一個在后臺運行的現代瀏覽器的 JavaScript API。它擁有很多特性,這些特性在以前的網站上都是沒有的,如離線支持、消息推送、背景同步等。我們現在正嘗試用 Service Worker, 但還是得在我們自己的網站上實現先。我向你保證,我們會做到的!
CDN因此,我們想要自己控制和部署我們的網站。而且現在我們也要采用CDN來擺脫由服務端和客戶端實際距離所帶來的網絡問題。盡管我們的用戶基本上都是荷蘭的,我們也想向世界的前端社區反映我們在質量、性能和推動網絡發展方面做的最好。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/87881.html
摘要:簡言之,我們認為好的用戶體驗從快速的內容傳輸開始,也就意味著性能美觀。每一步我們都在探討如何在獲得好的用戶體驗和保證設計美感的同時,最小化對性能的影響。字型子集設定到目前為止,子集設定是改善網頁字體性能最快的方式。 作者 Declan 原文鏈接 最近更新了我們的網站,它是經過了設計上的全面驗收的。但實際上,作為軟件開發者,我們會注重很多技術相關的零碎的東西。我們的目標是控制性能,注重性...
摘要:簡言之,我們認為好的用戶體驗從快速的內容傳輸開始,也就意味著性能美觀。每一步我們都在探討如何在獲得好的用戶體驗和保證設計美感的同時,最小化對性能的影響。字型子集設定到目前為止,子集設定是改善網頁字體性能最快的方式。 作者 Declan 原文鏈接 最近更新了我們的網站,它是經過了設計上的全面驗收的。但實際上,作為軟件開發者,我們會注重很多技術相關的零碎的東西。我們的目標是控制性能,注重性...
摘要:簡言之,我們認為好的用戶體驗從快速的內容傳輸開始,也就意味著性能美觀。每一步我們都在探討如何在獲得好的用戶體驗和保證設計美感的同時,最小化對性能的影響。字型子集設定到目前為止,子集設定是改善網頁字體性能最快的方式。 作者 Declan 原文鏈接 最近更新了我們的網站,它是經過了設計上的全面驗收的。但實際上,作為軟件開發者,我們會注重很多技術相關的零碎的東西。我們的目標是控制性能,注重性...
摘要:簡言之,我們認為好的用戶體驗從快速的內容傳輸開始,也就意味著性能美觀。每一步我們都在探討如何在獲得好的用戶體驗和保證設計美感的同時,最小化對性能的影響。字型子集設定到目前為止,子集設定是改善網頁字體性能最快的方式。 作者 Declan 原文鏈接 最近更新了我們的網站,它是經過了設計上的全面驗收的。但實際上,作為軟件開發者,我們會注重很多技術相關的零碎的東西。我們的目標是控制性能,注重性...
閱讀 3915·2021-11-16 11:50
閱讀 927·2021-11-11 16:55
閱讀 3659·2021-10-26 09:51
閱讀 856·2021-09-22 15:03
閱讀 3409·2019-08-30 15:54
閱讀 3260·2019-08-30 15:54
閱讀 2468·2019-08-30 14:04
閱讀 919·2019-08-30 13:53