關於 AMP,Webnovel 都做了些什麼?

閱文前端團隊發表於2019-05-14

本文作者:任家樂

原創宣告:本文為閱文前端團隊 YFE 成員出品,請尊重原創,轉載請聯絡公眾號 ( id: yuewen_YFE ) 獲取授權,並註明作者、出處和連結。

引言

AMP 是什麼?它全稱 Accelerated Mobile Pages 「AMP」,是 Google 推出的一個加速網頁載入的開源框架,我們在此也不做太多的介紹,具體可以看我們之前發的公眾號文章。閱文前端團隊作為國內最早踐行 AMP 的開發團隊之一,我們的 AMP 實踐也經歷了好幾個大迭代,其成果也得到了 Google 官方的肯定,分別在 Google I/O 2019 和 AMP Conf 2019 大會上被 feature(圖 1-1),希望我們積累的經驗可以給大家提供幫助。

圖片

圖片
「圖 1-1:閱文集團在 Google I/O 大會、AMP conf 2019 被 feature」

Webnovel with AMP

是否值得去做?

目前 Webnovel 先後進行了 2 次 AMP 頁面的轉化。首次 AMP 的實施輸出了站點的 2 個主要著陸頁:首頁、詳情頁,上線後 1 個月 Webnovel 的閱讀頁 PV 提升了 59%,可以歸功於 AMP 詳情頁的轉化。第二次我們則將 Webnovel 主要路徑頁面進行了 AMP 的轉化(閱讀頁、書庫頁、漫畫詳情頁、漫畫閱讀頁等),目前從 Google Analytics「GA」的資料來看,還是非常值得去實施的 :這些 AMP 頁面平均載入時間為 0.94s, 而被 AMP Cache 快取的頁面載入時間甚至為 0。

我們做了哪些?

AMP 不僅是一個前端技術框架,它還提供了一套完整的生態,包含一系列 ”服務於“ 頁面載入體驗的規範和約束,其核心思想是,構建出載入速度更快甚至達到秒出的頁面,這要歸功於它提供的 3 個重要元件:

  • AMP HTML - 提供了一系列 AMP 自定義的 HTML 標籤及規則,有效地保證了 HTML 的載入體驗。
  • AMP JS - 提供了一系列 JS 元件,其資源直接來源於 Google CDN。
    • 為了達到極致的載入體驗,AMP 並不允許開發者引入自定義的 JavaScript,而是提供了大量的 AMP JS 元件來實現使用者想要達到的效果( AMP Conf 2019 新引入的 amp-script 可以幫助解決自定義元件不能完成的效果,不過當前這個功能還在實驗當中)。
  • AMP Cache - 利用 Google 的快取及預載入方案可以達到頁面的秒出。

那麼使用者體驗與開發體驗是否可以達到能夠接受的平衡點?我們先來看看 Webnovel AMP 具體的實施細節吧。

AMP HTML

Webnovel 的 AMP 頁面採用了 EJS 模板引擎作為直出方案,和普通的 EJS 專案唯一的區別就是需要遵循 AMP HTML 的一些規則。 AMP HTML 提供了簡單的 HTML 模板,並對一些 HTML 標籤進行了規則的約束,只要遵循它的文件說明,還是能夠很快接入的。當然,Webnovel with AMP 最重要的實施步驟則是應用它的元件, 也就是「AMP JS」。

圖片
「圖 1-2:AMP HTML 模板」

圖片
「圖 1-3:AMP HTML 標籤的規則」

AMP 元件的約束

在參加 AMP 會議之前,我可能會說,這裡需要先給各位打個預防針啦!在 AMP 的世界裡,你不能夠引入自己的指令碼、不能外鏈引入自己的樣式,只能一切按它的規則走!但此次 AMP 會議出乎意料地帶來了一個新的技能 - amp-script 的支援,我們終於可以寫自己的指令碼了!但需要注意的是,amp-script 僅允許解壓後最多 150KB 的大小,雖然如此,我們也可以方便地利用其非同步載入一些我們自己的指令碼。 但為什麼 AMP 對指令碼有很多約束?來看下 AMP 的官方文件中關於指令碼的說明:

“JavaScript is powerful, it can modify just about every aspect of the page, but it can also block DOM construction and delay page rendering (see also Adding interactivity with JavaScript). To keep JavaScript from delaying page rendering, AMP allows only asynchronous JavaScript. AMP pages can’t include any author-written JavaScript” (即:JavaScript很強大,它可以改變一個頁面的任何方面,但它同時也阻礙了 DOM 的生成、頁面的渲染。為了避免它對渲染的阻礙,amp 僅僅允許非同步載入 JavaScript,但它並不允許引入任何頁面作者寫的指令碼)

指令碼可以阻礙渲染,而為了保證快速呈現頁面內容,指令碼的約束似乎不可避免,對於 amp-script 大小的限制,也是為了保證在低端手機上依然有不錯的載入體驗。

AMP 元件的基礎應用

AMP 提供了超級多的元件,只需: 1、外鏈引入該元件提供的 JavaScript 指令碼。 2、找到元件示例程式碼、嵌入 HTML DOM 結構中,按需更改元件引數。

圖片

「圖 1-4:元件一覽表」

AMP 文件中,每個元件基本都有具體的示例程式碼, copy 下來就可以在專案中使用,這一點很贊!但想要非常 “精準地” 實現我們想要的互動效果,還是非常難的,畢竟這個元件不是我們自己寫的,我們也不能夠擴充它,這種感覺就好比我們有手有腳、卻只能用假肢,身體變輕盈了,但行動受到了很大的限制,不過比較欣慰的是,AMP 的常用元件也基本滿足了我們的需求。這裡例舉了一些 Webnovel 使用的 AMP 常用元件:

  • amp-img

遵循 AMP HTML 的規則,所有的圖片都需要用 實現,它用於響應式地展示圖片、並完美自帶懶載入功能(不在視區內不進行載入)。目前 Webnovel 的漫畫閱讀頁,所有的圖片都用其實現了寬度 100%、高度自適應(圖 1-5)。

圖片
「圖 1-5:amp-img 輕鬆實現圖片高度自適應」

在此之前我們是將圖片絕對定位,同時在容器上新增樣式「padding-top:圖片寬高比 」來實現的,相比之下 <amp-img> 更方便:

圖片
「圖 1-6:舊的實現方式」

圖片
「圖 1-7:使用設定 layout 為 responsive 即可」

  • amp-list

目前我們大部分 AMP 頁面都使用了這個元件,只要是非同步載入某些模組,就會有它的用武之地(圖 1-8):

  1. 書詳情頁 - 打賞資訊、標籤資訊、書評的非同步載入。
  2. 漫畫列表頁 - 分頁載入漫畫書籍
  3. 漫畫閱讀頁 - 分頁載入漫畫章節圖片

圖片
圖片
圖片
「圖 1-8:詳情頁、漫畫閱讀頁、漫畫列表頁 amp-list 非同步載入模組」

  • amp fallback & placeholder

非常讚的 API !有了它,我們無需檢測載入失敗、載入超時的情況,只需設定好該情況對應的 UI 展示即可!amp-imgamp-list 等元件中,只需在元件內的 DOM 元素標籤上新增 fallback & placeholder 屬性即可。

  • amp-mustache

提供 mustache 模板引擎,一種 logicless「弱化資料邏輯」 的模板語言, 通常配合 amp-list 等非同步載入元件來使用,amp-list 發起請求拿到資料後,會渲染其中的 mustache 模板、完成資料、模板的拼接。

  • amp-sidebar

用於側邊欄、工具欄等。目前我們左側滑出的側邊欄就是利用它實現的(圖 1-9),實現成本很低,只需將其對應的 DOM 結構放置於 body 下,同時在觸發側邊欄展示的元素上繫結 AMP 提供的 tap 事件。

圖片
「圖 1-9:amp-siderbar 實現側邊目錄」

  • amp-bind

可配合 amp-state 使用,amp-state 元件用於初始化 json 資料,而 amp-bind 可以繫結資料到 DOM 元素上,同時支援 amp.setstate()amp.pushstate() 等方法實現資料的更新。目前頁面中需要動態展示的元素、文字,我們通過它繫結了資料、資料改變後頁面對應的元素、文字也會對應地變成繫結的資料。 比較侷限的方面是,只有在觸發事件後資料才會生效,不適用於頁面 onload 時的資料邏輯處理。

  • AMP 的事件機制

AMP 也支援事件的處理,例如 tap 點選事件、change 事件等,更高階的有:滾動到某位置觸發動畫等效果,具體可參考 AMP 文件。

AMP Cache

AMP Cache 算是 AMP 的核心概念了,簡單來講,通過 Google 搜尋引擎搜尋到的 AMP 頁面可以被 AMP 快取,同時也會被 Google 進行預載入,Google 使用的一些安全性機制、快取更新機制,可以讓開發者更無憂地使用。AMP 也提供了被快取頁面的 CDN 地址拼接規則,利用這個快取優勢,Webnovel 將所有 AMP 頁面之間的跳轉連結改為了 AMP Cache 的地址,如果所有 AMP 頁面都成功被 Cache ,那麼頁面之間幾乎可以做到無縫切換(圖 1-10),如果頁面沒有被 Cache,也不用擔心會跳轉到未知的 404 頁面,因為 AMP Cache 會將其重定向到我們自己站點域名下的 AMP 頁面。

圖片
「圖 1-10:利用 AMP Cache 實現 AMP 頁面無縫切換」

Webnovel AMP 頁面的體驗優化

漫畫閱讀頁多個 AMP 元件結合使用打造更好的互動體驗

Webnovel 漫畫閱讀頁提供了另外一種不同於小說的閱讀方式,由於漫畫的閱讀相比於小說更為方便快捷,因此其載入體驗變得尤為重要,這裡 Webnovel 利用 AMP 元件對漫畫閱讀頁的載入體驗做了優化,原本「重新整理頁面」切換章節的體驗優化為「無重新整理」載入章節內容。

amp-list、amp-form 及 amp-state 合力實現無重新整理向下載入

除了服務端渲染的首章節,其它的章節內容若要實現非同步載入,amp-list 元件是必然要用的,需要注意的是,如果其 src 引數為介面地址,那麼頁面 onload 時就會觸發,但我們希望做到的是點選下一章再進行載入,因此實現方案為:

  1. amp-state 元件初始化章節模板所需 json 資料(圖 2-1),其 id (例如 comicContent)可看作該 json 資料的變數名。
  2. amp-list 去除 src 引數,改為 [src] 引數,其值為上一步的 comicContent(圖 2-2)。
  3. 新增 amp-form 元件,其 action 引數值為下一章節的介面地址,同時引數 on 中處理表單提交成功的邏輯(圖 2-3), 即:獲取資料後更新章節陣列,這將會重新渲染 amp-list 中的章節模板。

圖片
「圖 2-1: amp-status 初始化的資料」

圖片
「圖 2-2: amp-list 中繫結 amp-state 中的資料」

圖片
「圖 2-3: amp-form 的成功回撥」 關鍵點:

  • amp-state 中定義的章節資料需要前端自己維護一個陣列(圖 2-1 中的 chapters 欄位)來儲存各章節,實現 amp-list 中迴圈渲染章節模板,展示所有載入的章節。
  • amp-form 中的 submit-success 邏輯中,需要通過 AMP.setState() 更新章節陣列,將最新章節 push 進陣列。
  • amp-form 中的 submit-success 回撥僅僅是介面請求成功的回撥,請求成功不代表業務邏輯中也是成功的,因此需要通過業務介面成功與否的標識欄位再次區分成功和失敗的邏輯。
  • amp-state 最多儲存 100kb 的資料,前端需要處理載入章節過多的情況,例如快取當前載入的章節數,若超過一定數量,點選下一章重新整理頁面。

最終實現出來的效果:

圖片
「圖 2-4:無重新整理載入下一章漫畫」

小說閱讀頁 amp-list 元件進階應用

在上一節中,通過 amp-listamp-formamp-state 3個元件的結合使用,終於實現了無重新整理載入下一章,其實 amp-list 近期已提供實驗性高階 API: load-moreload-more-bookmark 等引數,可以做到無限載入,並同時支援點選載入、無限滾動載入2種方式,無需前端自己維護章節陣列,所有的一切都由 amp-list 自己實現。這裡對小說閱讀頁進行了實踐。

amp-list-load-more 實現無限滾動載入

amp-list-load-more 的實踐非常簡單,只需在 amp-list 元件中,加入 load-more、load-more-bookmark 引數即可(圖2-4),具體 api 說明可參考 amp-list 的文件。雖然當前功能為實驗性功能,但相信 Google 不久後就會在正式環境進行支援。

圖片
「圖 2-4:amp-list-load-more 程式碼片段」

由於 amp-list-load-more 是 AMP 的實踐性功能,除了新增引數,還是需要做些準備工作的。

  1. 正式環境中,需要在小說閱讀頁的訪問地址域名下(webnovel.com 或 AMP cache 的 Google 域名)種一個 Cookie(name: AMP_EXP,value: amp-list-load-more)才可體驗此功能。
  2. load-more-bookmark 引數只能為章節返回資料中的欄位名稱,其值必須為下一章的介面地址,不支援前端自己拼接地址,因此需要後端配合新增此欄位。
  3. 介面返回的下一章 url 不能為相對路徑,必須為帶協議頭、自己站點域名的 url,否則在 Google 域名下請求地址的域名會出現問題。

最終實現效果:

圖片

Webnovel 更多的 AMP 實踐

當然,Webnovel 不只用了上文中提到的 AMP 基礎元件,也沒有止步於元件級別的體驗優化,Webnovel 還使用了 AMP 主推的一些王者功能。

更優的體驗 - AMP 主推功能的實踐

Signed HTTP Exchange 「SXG」

它也是 AMP conf 2019 的亮點,其效果為:訪問了 Webnovel Google 域名下的 AMP 頁面,瀏覽器 url 地址展示的是 Webnovel 主站的域名(如圖 3-1)!這是 AMP 今年主推的功能之一,有些公司已進行實踐,例如 Yahoo Japan,而 Webnovel 也抓住了時機、成功地進行了實踐,其效果及實現細節可以參考「 Webnovel 的 SXG 實踐 by 劉鵬」。

圖片
「圖 3-1:Webnovel SXG 實施效果」

amp-story

算是 AMP 相當主推的功能了!使用其提供的多樣性模板可以更加豐富地全屏展示 Webnovel 的各種故事「 關於 AMP Story,你需要知道這些 by 芯芯」,視訊和 animation 的結合使 Webnovel 的使用者可以更沉浸的瀏覽書籍。amp-story 還提供本地化、相容桌面與移動端的展示等功能,此次 AMP 會議還帶來了 amp-story 的一些新推進,例如 amp-story 自動生成工具、 Google Search 結果頁直接收錄並展示 AMP Story 等多方面的支援,可以說是非常牛了。

AMP conf 2019

目前 AMP 還有很多值得實踐的功能,這次 Google 團隊在東京舉辦的 AMP Conf 2019 也帶來了很多新的想法,不少來自世界各地的開發、產品、設計都簇擁於此,可見 AMP 已逐漸具備廣闊的市場。我們也很幸運地被邀請參加這次會議,一起見證了 AMP 的新技術及主推的功能、同時也從世界各個公司的 AMP 案例中,再次深刻地體會到了 AMP 技術的價值、潛力。

圖片
「AMP conf 2019 in Tokyo」

總結

一切新技術的應用都應該服務於使用者,而衡量一個技術是否值得實施的途徑之一就是看資料。Webnovel 在實踐 AMP 後,最顯著的改變非常符合 AMP 的核心目標 - 頁面載入體驗的極致提升(87% 的提升),除此之外,GA 的資料也證實了一些其他的優勢,例如,Webnovel 主要頁面的 PV 在應用 AMP 技術後有所提升(閱讀頁 PV 增加近 59%)、Webnovel Google 搜尋引擎的來源提升了 18%,從資料上來看 Webnovel 的 AMP 實踐是非常有意義的。

檢視更多分享,請關注閱文前端團隊公眾號:

關於 AMP,Webnovel 都做了些什麼?

相關文章