Home Blogs Layer0がReact PWAからAMPを自動的に生成する方法
Applications

Layer0がReact PWAからAMPを自動的に生成する方法

About The Author

Outline

AMPConf 2019はまだ終わったばかりだが、まだ始まったばかりだ! この一連のブログ記事では、React StorefrontフレームワークとLayer0が開発者がReactアプリでAMPをサポートしやすくする方法を強調することで、AMPConfを称える。

アンペアを乾燥させた状態に保つ

プログレッシブ・ウェブ・アプリ(PWA)とアクセラレーテッド・モバイル・ページ(AMP)の両方で、eコマースを比較的早期に導入している。 Reactを搭載したPWAにより、開発者はネイティブアプリに匹敵する魅力的な体験をウェブ上で提供できる。 しかし、検索生成トラフィックに関しては、AMPは可能な限り最速のオプションを提供する。

実際、Googleが推奨するカスタマージャーニーは、まずユーザーを検索するためにアプリのAMPバージョンを配信し、後続のページでサイトの完全なPWAバージョンに移行することである。 また、小売業者のウェブサイトトラフィックの半分近くがオーガニック検索によるものであるため、AMPとPWAの両方をサポートすることが優先事項となっている。

残念なことに、PWAとAMPの技術はこれ以上大きく異なることはない。 PWAはReact、Vue、Angularのような現代的なライブラリを使用しており、そこではJavaScriptがHTMLやCSSのレンダリングと対話性の提供という中心的な役割を担っている。 一方、AMPページはJavaScriptの使用が完全に禁止されており、CSSとHTMLの両方に厳しい制限がある。 その結果、AMPとPWAの両方をサポートするには、開発者は通常、アプリケーションのかなりの部分をAMPで再コーディングする必要がある。 開発チームの負担はそれだけではない。 バグ修正、レイアウト変更、新機能などは、AMPとPWAの両方のコードベースに伝播する必要があるかもしれない。

素晴らしいアプリを一度書くのは難しい。 誰も同じアプリを二度と書きたくない。 開発者はこの種のものを嫌っており、DRY (Don Not Repeat Yourself)という一般的な頭字語を与えている。 開発者として、私たちはeCommerce PWA向けに作成したReactフレームワークに自動AMPサポートを追加することに早期に投資した。 このようにして、開発者はReactでプログレッシブウェブアプリを書いて、余分な開発努力なしにAMPサポートを受けることができる。

そしてそれは私達の顧客のために非常によく働いた。 React Storefrontを使ってAMPを実装するには、アプリを再構築する代わりに、通常は1日か2日かかり、そのほとんどは、すべてが期待どおりに機能することを確認するだけである。

この記事では、React StorefrontがAMPとPWAを単一のコードベースからサポートするためにどのようにして苦労しているかを説明する。 次回は、複雑なエンタープライズコンテキストでAMPを提供するのに役立つLayer0のいくつかのエキサイティングな新機能を共有する。

なぜすべてのReactフレームワークがこれを行わないのか?

典型的なReactアプリでは、AMPコンテンツを自動的に生成するのは難しい。 これは、ほとんどのReactアプリがブラウザでのみ動作するように設計されているが、AMPコンテンツはブラウザに到達する前にJavaScript (Reactを含む)を持たないためである。 言い換えれば、Google AMP Cacheにブラウザに送信したのと同じReactコードを指すだけではだめだ。 それらは完全に異なったフォーマットである。

この制限を克服するために、React StoreFrontアプリをデフォルトでユニバーサル(同型と呼ばれることもある)にし、Layer0でサーバーサイドレンダリング(SSR)をサポートするという初期アーキテクチャ上の決定から恩恵を受けた。 SSRでは、ページのレンダリングはユーザーに提供される前にサーバー上で行われる。 SSRを追加する際の主な目標はパフォーマンスとSEOを改善することであったが、サーバー上でReact Storefrontアプリを実行し、以下のテクニックと連携してHTML出力を有効なAMP HTMLに自動的に変換することも可能になった。

AMPがサポートされていることをGoogleに通知する

AMPを実装するための最初のステップは、あなたのページのAMPと同等のものが存在することをGoogleのクローラーに通知することである。 通常、ページのAMPバージョンを別に作成し、アプリケーションのルーターを設定して、AMPとPWAの両方のコンテンツを異なるURLで提供する必要がある。 React Storefrontでは、トップレベルページコンポーネントに@withAmpデコレータを追加するだけでよい。 React StorefrontはURLに“.amp”を追加するだけで、どのページでも有効なAMPHTMLを自動的にレンダリングする。 @withAmpデコレータはこの規約を利用して、必要なリンクタグをドキュメントヘッドに追加する。

言い換えれば、

				
					@withAmp
class Product extends Component {
  ...
}
				
			

PWAページで次のような結果になる:

				
					<link rel="amphtml" href="https://www.mysite.com/p/1.amp"/>
				
			

Googleのクローラーは/p/1へのリンクを見ると、AMPコンテンツをダウンロードし、GoogleのAMP CDNから直接提供する。

適切なSEOのために、AMPページは、以下のようなページの元のPWAバージョンにrel=canonicalタグを埋め込む必要があることに注意:

				
					<link rel="canonical" href="https://www.mysite.com/p/1"/>
				
			

AMPページと非AMPページを適切な(ただし異なるバージョンの)<リンク>タグで相互に参照することの重要性をここで強調する価値がある。 これらのセットアップがきちんとなければ、GoogleはあなたのAMPの内容を提供しないし、さらに悪いことに、それはあなたのAMPページがあなたの非AMPページのSEOランクを共食いすることになるかもしれない。 React Storefrontはあなたのためにすべての「AMP二重入力簿記」を行うので、誰かが正しいタグを更新するのを忘れたので、このことを心配する必要はない。

AMP対応コンポーネント

AMPで最も基本的な相互作用性を実装することは、大きな苦痛となり得る。 たとえば、AMPの単純な数量フィールドは次のようになる。

				
					<amp-form>
<amp-state id="product">
<script type="application/json">
      {
        "id": "123",
        "name": "Product",
        "quantity": 1
      }
</script>
</amp-state>
<input
    type="text"
    [value]="product.quantity"
    on="input-throttled:AMP.setState({ product: { quantity: event.value } })"
  />
</amp-form>
				
			

プログレッシブウェブアプリ内のすべてのインタラクティブコントロールに対して、このような2つのバージョンのコードを書くことを想像してみて。 打ち上げの締め切りだ!

ありがたいことに、私たちはあなたのためにそのハードワークをした。 React Storefrontは、QuantitySelectorのような粗いAMP認識コンポーネントを提供し、これらの残虐なディテールをすべて隠す。 React Storefrontでは、

				
					<QuantitySelector product={product}/>
				
			

Reactフレームワークは、GoogleがAMPページを要求したときにコンポーネントのAMPバージョンをレンダリングする。

条件付きレンダリング

ほとんどの場合、開発者はReact Storefrontフレームワーク内のAMP対応コンポーネントの1つを使用して、AMPでインタラクティブ性を提供することができる。 しかし、AMP固有のものをレンダリングする必要がある場合、フレームワークは、AMPで特定のコンテンツを条件付きでレンダリングするために使用できる、app状態のブール値のampフィールドを公開する。

例:

				
					import React, { Component } from 'react'
import { inject } from 'mobx-react'
@inject('app')
class MyAMPAwareComponent extends Component {
  render() {
    if (this.props.app.amp) {
      return (
        // AMP content
      )
    } else {
      return (
        // PWA content
      )
    }
  }
}
				
			

ユニバーサルアナリティクス

AMPの対話イベントの宣言的定義方法はReactとは全く異なる。 たとえば、Google Analyticsにイベントを送信して、特定の製品リンクのクリックを追跡したいとする。 AMPでは、次のようになる。

				
					<amp-analytics type="googleanalytics">
<script type="application/json">
    {
      "triggers": [
        {
          "on":"click",
          "event":"product_clicked",
          "selector":"#product1",
          "request":"event",
          "productID": "1"
        }
      ]
    }
</script>
</amp-analytics>
<a id="product1" href="/p/1" alt="Red Shirt">
<amp-img src="/images/products/1" height="100" width="100"/>
<div>Red Shirt</div>
</a>
				
			

Reactの実装は惜しまないが、onClickリスナーとga ()の呼び出しが必要になるだろう。 二人は全く似ていないと言うだけで十分だ。

React Storefrontは抽象化であるTrackコンポーネントを提供し、

				
					<Track event="product_clicked" productID={product.id}>
<a href="/p/1" alt="Red Shirt">
<Image src="/images/products/1"/>
<div>Red Shirt</div>
</a>
</Track>
				
			

サーバーでレンダリングされたHTMLをAMPHTMLに変換する

上記の戦略は、有効なAMPをレンダリングする方法の約80%を得る。 しかし、文書に加えなければならない追加の変更がある。 React Storefrontは送信前に送信HTMLを変換し、以下のようないくつかの変更を行う。

アンプボイラープレートとの追加⚡

AMPでは、文書内に特定の要素が存在する必要がある。 これらには、⚡ルートHTML要素の「」属性と、AMPボイラープレートと呼ばれる標準スタイル要素が含まれる。

				
					<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal
				
			

CSSの変換と統合

AMPでは、すべてのCSSが単一のstyle要素の本体で提供されることを要求している。 style属性と<リンクrel=”stylesheet”の使用は禁止されている。> React Storefrontはコードベース全体のすべてのスタイルを統合し、複数のスタイル<>要素やインラインスタイル属性に埋め込まれて、単一のスタイル<ampカスタム>要素にする。 Style属性を使用するたびに、React Storefrontは対応する規則を含む一意のCSSクラスを作成し、クラスを要素に適用し、style属性を削除し、クラスをamp-custom style要素に追加する。 言い換えれば、

				
					<div style="font-weight:bold">Red Shirt</div>
				
			

次のようになる。

				
					<style amp-custom>
  …
  .mi1 {
    font-weight:bold;
  }
</style>
<div class="mi1">Red Shirt</div>
				
			

CSSの自動変換により、ReactアプリからAMP互換のページを書く際のもう一つの大きな悩みを取り除くことができる。

マークアップをクリーンアップする

AMPがマークアップに課す規則は他にも様々である。 例えば、ReactDOMがboolean属性をレンダリングする方法では、無効なAMPHTMLが生成される。 このJSX:

				
					<script
  async
  custom-element="amp-sidebar"
  src="https://cdn.ampproject.org/v0/amp-sidebar-0.1.js"
/>
				
			

結果として次のHTMLが生成される:

				
					<script
  async
  custom-element="amp-sidebar"
  src="https://cdn.ampproject.org/v0/amp-sidebar-0.1.js"
/>
				
			

その結果、AMPバリデータに次のようなエラーが表示される。

CRUXがPWA/SPAの「電話」トラフィックのシェアを追跡できない

コンポーネントライブラリを使用する場合、コンポーネントによってレンダリングされたHTMLの一部がさまざまな理由でAMPバリデータと衝突する可能性がある。 React Storefrontは広く普及しているMaterial UIライブラリの使用を奨励し、生成するHTMLをクリーンアップするための特定のルールを提供する。 これは、状態管理からコンポーネントやスタイリングまでをカバーする包括的なReact Progressive Webアプリフレームワークを使用することで、開発者の速度を上げるという点でその価値を実際に示しているところだ。

AMPとPWAのインフラストラクチャ

AMPとPWAを実装している開発者は、アプリの2つのバージョンを実装し、その後の変更(つまり、すべての修正が2箇所でコードの変更になる)を通じてそれらを維持するか、自動化を使用してページからAMPコンテンツを派生させることができる。 Layer0では後者を選択し、顧客にとって非常にうまく機能した。 これまで説明してきたReact Storefrontの機能は、その成功の理由の一部に過ぎない。 次の記事では、このフレームワークがLayer0(Edgio)とどのように統合され、エンタープライズ環境でAMPをサポートするかを探る。 お楽しみに。