AMP

ホストされた AMP ページの最適化

このガイドでは、ウェブマスター向けに、ホストされた AMP ウェブサイトの最適化方法に関するヒントとガイダンスを提供します。

AMP はデフォルトで高速化されているのではないですか?

AMP ランタイムは高速化に最適化されているため、AMP ページが AMP キャッシュから配信される場合に、完全に最適化された上で、最高の読み込みパフォーマンスを発揮します。たとえば、ユーザーがモバイルの Google 検索からあなたの AMP ページたどり着いた場合、ページはデフォルトで AMP キャッシュから配信されるようになっています。

ただし、AMP ページは必ずしも AMP キャッシュから配信されるわけではありません。ほかのトラフィックソースにおいては自身のサーバーから AMP ページを表示するように、ウェブサイトで指定している可能性もあるからです。この場合の最も一般的なユースケースは、ユーザーが直接サイトにアクセスする、tasty.co のような AMP だけで構築されたサイトです。また、もう 1 つのトラフィックソースには、標準的なモバイルバージョンの代わりに AMP ページにリンクし始めた Twitter が挙げられます。つまり、ユーザーが Twitter のモバイルアプリでリンクをクリックすると、サイト運営者オリジンの AMP バージョンに移動することになります(存在する場合)。

その結果、AMP ページが AMP キャッシュからのみ配信されるという確信を必ず持つことができません。このように、独自のサイトから AMP ページを配信する場合、AMP ページが最適な読み込みパフォーマンスを提供できるようにすることが重要となります。

AMP ページはデフォルトで高速に読み込めるようになっていますが、ブラウザによる AMP ページの読み込みをさらに高速化するための追加のパフォーマンス最適化があります。このガイドでは、AMP ページを公開する際に考慮すべき最適化をいくつか説明します。このガイドを読み進める前に、すべての基本的なウェブパフォーマンスに関するベストプラクティスをすでに理解しておく必要があります。特に、読み込みパフォーマンスには、画像最適化が大きく影響します。

たとえば、以下の最適化テクニックを適用することができます。

"The Scenic" テンプレートは、3G 接続で 2 秒早く読み込まれます

詳細を省略する場合は、AMP ボイラープレートジェネレータを参照してください。これを使用して、カスタムの最適化 AMP ページを生成することができます。

AMP ランタイム読み込みの最適化

AMP では、<head> セクションに許可されるマークアップを制限していますが、依然として最適化の余地はあります。鍵となるは、レンダリングをブロックするすべてのスクリプトとカスタムフォントの読み込みができる限り高速化されるように、<head> セクションを構造化することです。

以下に、<head> セクション内の推奨されるコード順を示します。

<!doctype html>
<html  lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <meta name="description" content="This is the AMP Boilerplate.">
    <link rel="preload" as="script" href="https://cdn.ampproject.org/v0.js">
    <link rel="preload" as="script" href="https://cdn.ampproject.org/v0/amp-experiment-0.1.js">
    <link rel="preconnect dns-prefetch" href="https://fonts.gstatic.com/" crossorigin>
    <script async src="https://cdn.ampproject.org/v0.js"></script>
    <script async custom-element="amp-experiment" src="https://cdn.ampproject.org/v0/amp-experiment-0.1.js"></script>
    <!-- Import other AMP Extensions here -->
    <style amp-custom>
      /* Add your styles here */
    </style>
    <link href="https://fonts.googleapis.com/css?family=Inconsolata" rel="stylesheet">
    <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.selected}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible.selected}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible.selected}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible.selected}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible.selected}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
    <link rel="canonical" href=".">
    <title>My AMP Page</title>
  </head>
  <body>
    <h1>Hello World</h1>
  </body>
</html>

では、順を追って確認しましょう。

  1. 最初のタグは、meta charset タグで、その後に残りの meta タグを挿入します。

  2. 次に、<link as=script href=https://cdn.ampproject.org/v0.js rel=preload> で AMP ランタイム v0.js <script> タグをプリロードします。AMP ボイラープレート は AMP ランタイムが読み込まれるまで body { visibility:hidden } 経由でドキュメントを非表示にするため、AMP ランタイムはできるだけ早い段階でダウンロードし始めます。AMP ランタイムをプリロードすると、ブラウザに最優先でスクリプトをダウンロードするように指示されます。これを回避する方法については、server-side-rendering を参照してください。{amp-img6} {/amp-img6}

  3. ページにレンダリングを遅延させる拡張機能(amp-experiment、amp-dynamic-css-classes、amp-story など)が含まれる場合、AMP ランタイムがページをレンダリングするにはその拡張機能が必要であるため、拡張機能をプリロードします。

<link as="script" rel="preload" href="https://cdn.ampproject.org/v0/amp-custom-css-0.1.js">
<link as="script" rel="preload" href="https://cdn.ampproject.org/v0/amp-experiment-0.1.js">
<link as="script" rel="preload" href="https://cdn.ampproject.org/v0/story-1.0.js">
  1. Google Fonts を使う場合など、前もってフルリソース URL がわかっていない他のオリジンへの接続を高速化するために、preconnect を使います。
<link rel="preconnect dns-prefetch" href="https://fonts.gstatic.com/" crossorigin>
  1. AMP ランタイムを読み込みます。
<script async src="https://cdn.ampproject.org/v0.js"></script>
  1. 遅延レンダリング拡張機能amp-experimentamp-dynamic-css-classesamp-story など)用に <script> タグを指定します。
  2. 残りの拡張機能(amp-bind など)用に <script> タグを指定します。これらの拡張機能は遅延レンダリングではないため、プリロードしてはいけません。初期レンダリングに必要な重要な帯域幅が奪われてしまいます。
  3. <style amp-custom> タグを使用して、カスタムスタイルを指定します。
  4. <head> セクションに使用できる他のタグを追加します。特に、外部フォントについては、レンダリングを阻害しないように最後に追加するようにしてください。
  5. 最後に、AMP ボイラープレートコードを指定します。ボイラープレートコードを最後に追加することで、カスタムスタイルが誤ってボイラープレート CSS ルールをオーバーライドしないようにすることができます。

AMP キャッシュはこのようなすべての最適化を自動的に実行します。AMP オプティマイザツールを使用すると、自分のオリジンで最適化を自動的に実行することができます。

ヒーロー画像のプリロード

AMP HTML は、amp-img という独自の画像要素を使用します。amp-img には、従来の HTML img タグに比べて多くのメリットがありますが、AMP ランタイムが読み込まれてからでないと画像ダウンロードを開始できないという欠点があります。製品ページのヒーロー画像といった一部の画像では、画像をできるだけ素早く読み込むことが非常に重要となります。こういった場合は、画像をプリロードし、ブラウザができる限り早い段階でダウンロードできるようにし、AMP ランタイムが読み込まれるまで待機しないでいいようにすることが最善です。

<head>
  <link rel="preload" href="/images/elephants.png" as="image">
</head>
<body>
  ...
  <amp-img width="404" height="720" layout="responsive"
           src="/images/elephants.png" alt="..." >
  </amp-img>
</body>

しかし、レスポンシブレイアウトに、画面の幅によって異なるヒーロー画像が必要な場合はそうすればよいのでしょうか。たとえば、以下のように、デスクトップには幅広い画像を指定し、モバイルには幅の狭い画像を指定するといった場合です。

<amp-img width="404" height="720"
    alt="..." layout="responsive"
    src="/images/elephants_narrow.png"
    media="(max-width: 415px)">
</amp-img>
<amp-img height="720"
    alt="..." layout="fixed-height"
    src="/images/elephants_wide.jpg"
    media="(min-width: 416px)">
</amp-img>

便利なことに link rel=preload はメディアクエリもサポートしているため、以下のように、preload 文に同じメディアクエリを使用することができます。

<link rel="preload" as="image"
    href="/images/elephants_narrow.png"
    media="(max-width: 415px)">
<link rel="preload" as="image"
    href="/images/elephants_wide.jpg"
    media="(min-width: 416px)">

ちなみに、同じアプローチは、amp-video ポスター画像にも使用できます。

<link rel="preload" href="/images/poster.jpg" as="image">
...
 <amp-video width="480" height="270" src="elephant.mp4"
             poster="/images/poster.jpg"
             layout="responsive">
     ...
</amp-video>

preload 文は、必ずビューポートの宣言のに配置するようにしてください。ブラウザが画面の幅を判定するには、ビューポートのサイズが必要です。

<meta name="viewport" content="width=device-width">
...
<link rel="preload" media="(max-width: 415px)" ...>

重要な画像のみをプリロードするようにしてください。画像のダウンロードによって、ほかの重要なダウンロードに必要な帯域幅が消耗されてしまう可能性があるためです。

サーバーワーカーの使用の検討

すべての主要なブラウザはサービスワーカーをサポートするようになったため、サービスワーカーをサイトに追加すべきかどうかを評価するとよいかもしれません。

確実に高速なナビゲーションを実現できるとわかっているアーキテクチャ上のパターンには 2 つあります。

  • シングルページアプリケーション: アプリシェルモデル(AMP コンテキストでは AMP-in-PWA と呼ばれる)です。このパターンでは、サービスワーカーが AMP ドキュメントをアプリシェルベースの PWA エクスペリエンスにアップグレードする必要があります。
  • マルチページアプリケーション: 合成リソースのストリーミング。サービスワーカーは静的なヘッダーとフッターをキャッシュし、ストリーミングを使用して、コンテンツを読み込みながらキャッシュされた部分的なレスポンスを即時に返します。

上記のいずれのパターンも使用されておらず、全サイトをキャッシュするのが不可能な場合(小規模なサイトであれば可能でしょうが)、サービスワーカーはパフォーマンスに悪影響を及ぼす可能性があります。この場合には、サービスワーカーを使用しないのが最善と言えます。

ただし、ウェブサイトをホーム画面にインストール可能にする場合、またはオフラインでエクスペリエンスを提供する場合は、サービスワーカーを使用する必要があります。この場合は、ナビゲーションプリロードを使用し、潜在的な減速を緩和することが重要です(注意: 現在のところ、ナビゲーションプリロード機能は、Chrome でのみサポートされています)。

以下は、AMP ウェブサイトがサービスワーカーを使用する場合のベストプラクティスです。

  • AMP ランタイムと拡張機能(amp-carousel など)をプレキャッシュします。
  • ほとんどのページで使用されるロゴ、フォント、およびその他の静的コンテンツをプレキャッシュします。
  • ロゴ、フォント、および画像の配信には、cache-first strategy を使用します。
  • AMP ランタイムおよび拡張機能の配信には、stale-while-revalidate ストラテジーを使用します。
  • ナビゲーションリクエストにネットワーク優先ストラテジーを使用する場合は、ナビゲーションプレロードを有効化します。

AMP サイトでサービスワーカーを使用し始めようと考えている方は、上記のすべてのベストプラクティスを実装するサービスワーカーを提供するこちらのサンプルをお試しください。

AMP ランタイムは、更新を素早く利用できるように、max-age を 50 分にして配信されています。ブラウザのキャッシュミスの可能性を回避するために、AMP ランタイムをサービスワーカーから配信するようにすると良いでしょう。

プリキャッシュは、キャッシュされた AMP ページからオリジン上の非 AMP ページに移行するだけでなく、キャッシュされた AMP ページからオリジン上の AMP ページに移行する場合にも関係があります。これは、AMP キャッシュがエバーグリーン URL から最新のリリースバージョンに AMP ランタイム URL を書き換えるためです。以下にその例を示します。

https://cdn.ampproject.org/v0.js -> https://cdn.ampproject.org/rtv/001515617716922/v0.js.

その結果、自分のオリジンから配信される AMP ページはブラウザのキャッシュ機能の恩恵を受けないため、この場合はもう一度(バージョン管理されていない)AMP ランタイムをダウンロードしなければなりません。サービスワーカーを使用すると、バージョン管理されていない AMP ランタイムをプリキャッシュし、移行を高速化することができます。AMP キャッシュが AMP ランタイム URL をバージョン管理する理由については、こちらのドキュメントを参照してください。

Safari では、ページが AMP キャッシュから配信される場合にオリジンにサービスワーカーをインストールできないという、サービスワーカーの実装方法に関する大きな違いがあります。

カスタムフォントの最適化

AMP では、フォントの読み込みを最適化する方法がいくつかあります(ほとんどの方法は、実際のところ AMP 固有の方法ではありません)。

  • 可能であれば、font-display: optional を使用します。この場合、すでにキャッシュに存在するフォントのみが使用され、カスタムフォントがまだ読み込まれていない場合は、システムフォントにフォールバックします。
  • ウェブフォントを最適化します(WOFF2 を使ってカスタムフォントを配信するなど)。
  • カスタムフォントを以下のようにプリロードします。
<link rel="preload" as="font" href="/bundles/app/fonts/helveticaneue-roman-webfont.woff2" >
  • Google フォントを使用している場合、またはフォント URL が不明なフォントプロバイダーを使用している場合は、各フォントサーバーに事前に接続(preconnect)します。
 <link rel="preconnect dns-prefetch" href="https://fonts.gstatic.com/" crossorigin>

最後に、ただし重要なこととして、ページで使用するカスタムフォント数を最小限に抑えるようにします。可能であれば、カスタムフォントの代わりにシステムフォントを使用してください。システムフォントは、ウェブサイトをユーザーのオペレーティングシステムに一致させることができます。また、読み込まれるリソースを減らすことができます。

サーバー側レンダリングの AMP レイアウト

サーバー側レンダリングの AMP レイアウトは、読み込み時間をさらに高速化するために AMP キャッシュが使用するテクニックです。サーバー側レンダリングを使用すると、AMP ボイラープレートを削除することが可能になるため、AMP ランタイム JavaScript を実行せずに AMP ドキュメントをレンダリングできます。たとえば、サーバー側でレンダリングされた AMP ボイラープレートジェネレータは通常の AMP バージョンよりも 2 倍も高速にレンダリングされます!

AMP ページを公開している場合は、ぜひ AMP オプティマイザの使用を検討してください。AMP オプティマイザを使うと、サーバー側レンダリング AMP レイアウトを含み、独自のバックエンドから最適化された AMP ページを配信することができます。また、このドキュメントで説明されたその他の多くの最適化を自動的に実行することもできます。

基本的な最適化

もちろん、すべての基本のウェブパフォーマンス最適化は、AMP ページにも適用されます。