Google 移動端性能優化利器 —— AMP

來自專欄阿里媽媽前端快爆20 人贊了文章

AMP 介紹

AMP 全稱 The Accelerated Mobile Pages, 是 Google 提供的一個開源庫,用於提高靜態頁面的性能, 進而提升用戶體驗。這裡的靜態頁面並不是指沒有和服務端交互的頁面,而是以內容為主的弱交互頁面。典型的就是新聞、諮詢頁面。通常 AMP 是前端性能優化的利器。

直接 Show 效果 AMP 頁面秒開

1、Google 搜索 MP3 alibaba 關鍵詞,在控制檯中可以發現 AMP 頁面被預先載入。

2、 點擊該內容。頁面秒開 TTFB=0。

3、性能對比

在項目中,我們針對原有的頁面進行了 AMP 化,相關性能數據基於 WebPagetest 統計,具體數據如下:

非 AMP 頁面

AMP 頁面

AMP Cache

整理如下:

AMP 的優勢

  1. AMP 能夠帶來 SEO 排名優化。
  2. 提供 Google 免費的 CDN,用於緩存頁面。
  3. Google 搜索結果對 AMP 頁面有預載入處理,能讓用戶更快地到達我們的著陸頁。

適用場景

弱交互頁面,強 SEO 訴求,頁面主體以內容為主最好以新聞諮詢為主。當然電商場景 AE、Alibaba M站、 eBay 等已經使用上了。主要使用場景是國外場景,國內環境很多 AMP 的靜態資源文件處於半翻牆狀態,使用場景有限。失去了Google AMP 緩存, AMP 性能將大打折扣。所以現目前使用場景基本上是海外業務 ,不過其優化思想倒是可以好好借鑒。

AMP 如何提升網頁性能

  1. 僅允許非同步腳本

由於同步 JS 會阻塞 DOM 構建,AMP 中只能使用非同步的 JS,且頁面中不能引入用戶自定義的JS 腳本, 需要頁面交互的地方可以使用 AMP 提供的相應組件,這些組件是經過了精心設計,不會導致性能下降。

2. 資源載入和文檔佈局解耦

外部靜態資源(例如圖片、iframe 等)必須在 HTML 中聲明資源大小,這樣頁面在所有資源載入完畢之前,就可以開始頁面佈局,避免瀏覽器重繪。

3. 第三方 JS 隔離

第三方 JS 對用戶來講大多是黑盒,裡面可能存在同步操作和頁面信息修改和 DOM 修改等操作,從而導致阻塞頁面渲染和瀏覽器重繪等嚴重問題。因此 AMP 使用 iframe 將第三方資源進行隔離,保證主頁面的性能。

4. CSS僅支持內嵌引入並限制大小

CSS 會阻礙頁面的渲染, 這一優化,可以減少渲染環節的額外 HTTP 請求開銷。

5. 使用GPU 加速

6. 設定資源載入的優先順序

傳統的資源載入順序是有瀏覽器來控制的, 而 AMP 是通過 AMP Runtime 來控制資源的載入順序的,比如首屏資源優先載入,非首屏資源滾動到視窗才載入。具體的載入順序由 cdn.ampproject.org/v0.j 腳本控制。

7. 瞬時載入頁面

使用 preconnect API 在用戶實際選擇頁面之前,頁面就可能已經準備就緒。AMP 中做了特殊優化,只會下載實下載首屏資源,且大量消耗GPU的資源不會被下載,例如 iframe。

AMP Cache

通過書寫 <html ?><html amp>標識當前頁面類型為 AMP 頁面,當 Google 搜索引擎抓取該頁面時, 會校驗當前頁面是否符合AMP格式是否符合規範, 如果符合規範,便會被Google 收錄,並添加到 Google AMP Cache。

被搜索引擎收錄之後,大多數用戶都是通過 Cache URL 直接訪問對應對應的 CND 緩存,而不是訪問源伺服器。

所以用戶通過 Google 搜索引擎訪問頁面時,Google 會根據其載入策略 preload 相應的 AMP 頁面, 也就是在用戶未訪問頁面之前,其對應的 AMP 頁面已經被瀏覽器預先載入, 這也是AMP 能夠實現頁面秒開的主要原因。

注意: AMP Chache 會緩存圖片和文檔信息, 如果頁面有千人千面等個性化需求, 需要使用amp-list 組件非同步請求服務端數據, 不然個性化數據會出現錯亂(與緩存策略更新有關,接下來會介紹)。

AMP Cache 更新策略

想要使用緩存,必須使用 AMP 提供成 Cache URL 訪問頁面,用戶每次從緩存中訪問 AMP 內容時,緩存會直接返回給用戶, 同時更新緩存,以便為下一個請求用戶提供最新的緩存。

遵循 Stale-while-revalidate 模型, 類似於 Service Worker 的離線更新策略。

AMP 開發流程

1、開發環境 playground

Google 提供了一個在線編輯的 IDE ampbyexample.com/playgr

<!doctype html><html ?><head> <meta charset="utf-8"> <title>My AMP Page</title> <link rel="canonical" href="self.html" /> <meta name="viewport" content="width_=device-width,minimum-scale=1"> <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript> <script async src="https://cdn.ampproject.org/v0.js"></script> <script async custom-element="amp-social-share" src="https://cdn.ampproject.org/v0/amp-social-share-0.1.js"></script> <style amp-custom> h1 { margin: 1rem; } .share-group { margin: 20px 0; } </style></head><body> <h1>Hello AMPHTML World!</h1> <amp-img src="/img/amp.jpg" width="1080" height="610" layout="responsive" alt="AMP"></amp-img> <section class="share-group"> <amp-social-share type="email"></amp-social-share> <amp-social-share type="facebook" data-param-app_id="254325784911610"></amp-social-share> <amp-social-share type="gplus"></amp-social-share> <amp-social-share type="linkedin"></amp-social-share> <amp-social-share type="pinterest" data-param-media="https://ampbyexample.com/img/amp.jpg"></amp-social-share> <amp-social-share type="tumblr"></amp-social-share> <amp-social-share type="twitter"></amp-social-share> <amp-social-share type="whatsapp"></amp-social-share> </section></body></html>

運行示例

2、 開發規範

  • JS 書寫 AMP 不允許載入自定義 JS,可以使用 AMP 提供的組件庫進行交互操作。
  • CSS 書寫 AMP 不允許通過 Style 標籤自定義 CSS,只能通過 <style amp-custom> 標籤書寫 CSS。
  • 事件綁定 示例:下面通過使用 on 綁定 tap 事件,然後通過 setState 改變狀態。

<div class="continue-reading-btn" on="tap:AMP.setState({showMore: true})"> Continue reading</div> <div class="article-content" [class]="showMore== true?content-expand:content-shrink"></div>

  • 非同步載入 大多數場景我們使用的是同步模板直出,但是,如果有千人千面,或者是個性化需求時,需要走非同步請求。因為同步數據會跟隨頁面進行緩存,導致個性化數據失效。這個時候可以使用 amp-list 非同步載入數據。

3、AMP收錄設置

有時一個頁面可能對應兩個版本, AMP 版本和 PC 版本, 當 Google 搜索引擎收錄非 AMP 版本時, 我們需要告訴搜索引擎, 這裡還有一個 AMP 版本的頁面也需要收錄。

非 AMP 頁面需要指向 AMP 頁面:

<link rel="amphtml" href="https://www.example.com/url/to/amp/document.html">

AMP 頁面需要指向 PC 頁面:

<link rel="canonical" href="https://www.example.com/url/to/full/document.html">

4、發布前校驗

本地開發完成之後,需要對 AMP 頁面進行校驗, 校驗未通過的頁面不會被 Google 收錄。常用的校驗工具:

  • AMP 在線校驗工具:ampbench.appspot.com/va
  • AMP Chrome 插件 校驗工具: chrome.google.com/webst

5、AMP 是否被緩存校驗

通過工具 生成對應的CDN緩存鏈接 ampbyexample.com/advanc

例如:alibaba.com/insights/vi 轉換後 CDN 鏈接:www-alibaba-com.cdn.ampproject.org 當轉換後的 CDN 鏈接可訪問,則說明緩存副本已經生成, 但是該副本何時出現在 Google 搜索結果中, 還需要等待 Google 收錄。

6、頁面打點統計

曝光打點:使用 amp-pixel 組件

<amp-pixel layout="nodisplay" src="https://gj.mmstat.com/7.gif?spm-cnt=$!{spma}.$!{spmb}&aplus&pre=DOCUMENT_REFERRER&href=SOURCE_URL&ampcid=CLIENT_ID(ampcid)&title=TITLE"></amp-pixel>

點擊打點:下面的事例是當點擊a標籤的時候, 向對應的日誌伺服器發送請求。這裡的日誌伺服器可以替換成自己需要的。

<amp-analytics> <script type="application/json"> { "requests": { "event": "https://amp-publisher-samples-staging.herokuapp.com/amp-analytics/ping?user=jghihrs3&account=ampbyexample&event=${eventId}" }, "triggers": { "trackAnchorClicks": { "on": "click", "selector": "a", "request": "event", "vars": { "eventId": "clickOnAnyAnchor" } } } } </script></amp-analytics>

感悟

如果你所涉及的業務有「出海」需求的話,不妨嘗試一下 AMP。國內業務可以參考 AMP 的性能優化原理。在筆者看來,AMP 並不是一套框架, 而是一套開發者規範。 用戶必須按照規範書寫,之所以這樣做的原因也是可以理解的,一行 JS 書寫有問題,便可能引發性能問題, 例如: 瀏覽器重繪等等。正在研究性能優化的同學可以閱讀下 AMP 實現源碼, 收穫一定滿滿。


推薦閱讀:
相關文章