既存のWebページをAMPに対応させてみる

閲覧しているWebサイトを離脱したい、と思うきっかけの代表的な要因に「表示速度が遅い」ことが挙げられるかと思います。
特に多数の記事ページがある情報発信系のブログやキュレーションメディアなどの表示が遅いと、どんなに質の良い記事があがっていても、そこから「他の記事も見てみよう」「継続して記事をチェックしていこう」という気持ちになれないかもしれません。

そんな表示速度によるユーザーの離脱を防止する一案として、近年Web界隈で話題になっているものがAMPです。

AMPとは?

AMPとは【Accelerated Mobile Pages】の略で、Googleが中心となって立ち上げた、モバイルページを高速で表示することを目的とするオープンソースプロジェクトのことです。
直訳で「加速されたモバイルページ」というその名のとおり、AMPで策定された仕様に沿ってモバイルページを構築すると、ページの表示速度は従来の約4倍、データ量は約1/10になると言われています。
さらに、ページの表示速度が向上することによってSEOにも効果があるとかないとか。(公式には明言されていないようです)

参考

高速化の仕組み

高速化の主な仕組みの1つに、AMPに対応したWebページのHTMLを事前にGoogleでキャッシュ(Google AMP Cache)しておくところにあります。
これにより、ページにアクセスしたときにページを1から読み込むのではなく事前に取得したキャッシュを表示するので、読み込み時間を大幅に削減できるようになっています。
また、AMP対応のJavaScript以外を許容しない、外部リソースのサイズをあらかじめ固定しておくなど、様々な制約を設けて読み込みや描画の負荷を減らすことも高速化・データ量削減に繋がっています。

具体的にどのくらい速くなるのかの検証結果は、本記事の後半【速度検証】に記載しています。

参考

AMP対応のWebページの見分け方

AMPに対応しているページは、Googleの検索結果でAMP対応ページを表すカミナリのようなマークが表示されています。


同じような見出しでAMPのマークがついてる記事とついていない記事があったとき、マークがついている方を選ぶと時間もデータ量も削減できるとなれば、ひとまずそちらを見てしまいそうですよね。
AMPのマークがユーザーに広く浸透すれば、離脱防止だけでなく流入の増加も期待できるかもしれません。

さて、先日そんなAMPに触れる機会がありましたので、今回は既存のWebページをAMP対応のWebページに書き換える流れをご紹介します。

AMP対応のWebページに書き換える手順

AMPを導入するためには、対象のWebページをAMPのテンプレートに沿ったマークアップにする必要があります。
AMPは「とにかくページの速度が遅くなるようなことをさせない」ことが優先されているので、ページを作成する上で様々な制約があります。
通常のWebページではできるのにAMPに対応する場合はできない・・・ということがしばしば。

特に独自のJavaScriptやJavaScript・jQueryのプラグインが使えないというのは、既存のページをAMPに対応させる際に少々厄介だったりします。

実際に通常のHTMLで組んだページをAMP対応のHTML(AMP HTML)に書き換えてみました。

AMP対応前のデモページ
↓↓↓
AMP対応後のデモページ

使用している要素は下記のとおりです。そのうち1〜3はAMPに対応させるための書き換えが必要なので次項から順に見ていきたいと思います。

  1. ロゴ
  2. ページトップボタン(jQuery)
  3. スライダー(JSプラグイン「slick」を使用)
  4. テキスト

事前準備(AMP HTMLに書き換え)

要素ごとのAMP対応を行う前に、HTML全体をAMPの形式に書き換えを行います。こちらの手順は公式のスタートガイドに日本語で詳しく載っているのでありがたいです。

AMP対応後のデモページの場合は下記のように書き換えました。

<!DOCTYPE html>
<!-- ▼ htmlタグに amp を追加します。-->
<html amp lang="ja" data-ng-app="App">
	<head>
		<!-- ▼ 文字コードは必ず UTF-8 を指定します。-->
		<meta charset="UTF-8">
		<meta name="format-detection" content="telephone=no">
		<!-- ▼ ビューポートを指定します。-->
		<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<title>AMP対応サンプル</title>
		<meta name="keywords" content="">
		<meta name="description" content="">
		<!-- ▼ canonicalを指定するタグを追加します。通常のHTMLバージョンがあれば指定、ない場合は自身のURLを指定します。 -->
		<link rel="canonical" href="https://bulan.co/swings/demo/amp-sample/amp/">
		<!-- ▼ AMPの基本スタイル(ボイラープレート)を追加します。 -->
		<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>
		<style amp-custom>
			/* ここにCSSが入ります */
		</style>
		<!-- ▼ ページの構造化データを追加します。 -->
		<script type="application/ld+json">
			{
				"@context": "http://schema.org",
				"@type": "WebPage",
				"headline": "BULANCO",
				"image": [
					"https://bulan.co/swings/demo/amp-sample/amp/assets/img/logo.png"
				]
			}
		</script>
		<!-- ▼ AMP JS ライブラリをインクルードするタグを追加します。 -->
		<script async src="https://cdn.ampproject.org/v0.js"></script>
	</head>
	<body>
		<!-- ここにコンテンツが入ります。 -->
	</body>
</html>

1.ロゴなどの画像のタグを変更する

ロゴおよびスライダーで使用している画像タグ(img)をAMPの画像タグ(amp-img)に変更します。

▼ 通常

<img src="./assets/img/logo.png" alt="ロゴ">

▼ AMP

<amp-img src="./assets/img/logo.png" alt="ロゴ" width="162" height="38" layout="responsive"></amp-img>

width/height属性は必ず指定しておきます。特にheightの指定が漏れているとAMPに対応できているかの検証を行う際にエラーが発生します。
また、layout属性を指定することでサイズの調整が可能です。画面幅に応じて可変する layout=”responsive” を使うことが多くなるかと思います。

公式リファレンス

2.スクロールトップボタン

ボタンクリックでページのトップにスクロールする機能は通常jQuery等で実装しますが、AMPページではjQueryを使用できません。
そのためAMP用に準備されているJSを組み合わせて実装します。
公式にサンプルがあるので、こちらに沿って進めれば比較的簡単に実装できます。

公式サンプル

公式リファレンス

1.head内で必要なAMP用のJSを読み込みます。

<!-- 指定位置でイベントを発火させるJS -->
<script async custom-element="amp-position-observer" src="https://cdn.ampproject.org/v0/amp-position-observer-0.1.js"></script>
<!-- アニメーションを実行するJS -->
<script async custom-element="amp-animation" src="https://cdn.ampproject.org/v0/amp-animation-0.1.js"></script>

2.bodyの下にページのトップの位置を示すタグとアニメーションの設定を記述します。

<!-- ページのトップはここです -->
<div id="top-page"></div>
<!-- ボタンを表示するアニメーションの設定 -->
<amp-animation id="showAnim" layout="nodisplay">
<script type="application/json">
	{
		"duration": "200ms",
		"fill": "both",
		"iterations": "1",
		"direction": "alternate",
		"animations": [{
			"selector": "#scrollToTopButton",
			"keyframes": [{
				"opacity": "1",
				"visibility": "visible"
			}]
		}]
	}
</script>
</amp-animation>
<!-- ボタンを隠すアニメーションの設定 -->
<amp-animation  id="hideAnim" layout="nodisplay">
<script type="application/json">
	{
		"duration": "200ms",
		"fill": "both",
		"iterations": "1",
		"direction": "alternate",
		"animations": [{
			"selector": "#scrollToTopButton",
			"keyframes": [{
				"opacity": "0",
				"visibility": "hidden"
			}]
		}]
	}
</script>
</amp-animation>

3.スクロールトップ用のボタンにアニメーション設定のselectorに指定したidと、クリックでトップの位置を示すタグまで移動するon属性を追加します。

<div role="button" tabindex="0" id="scrollToTopButton" on="tap:top-page.scrollTo(duration=200)" class="m-btn-pageTop">ページ<br>TOP</div>

4.アニメーションを発火させる位置にamp-position-observerのタグを挿入します。

▼ボタンを隠すアニメーションを実行するタグです。ページのトップ部分が表示された時に実行したいので、body直下付近に挿入します。

<!-- id="hideAnim"のアニメーションを実行 -->
<amp-position-observer on="enter:hideAnim.start" layout="nodisplay"></amp-position-observer>

▼ボタンを表示するアニメーションを実行、隠すアニメーションを無効にするタグです。ボタンを表示する位置に挿入します。

<!-- id="showAnim"のアニメーションを実行、id="hideAnim"のアニメーションを無効 -->
<amp-position-observer on="enter:showAnim.start; exit:hideAnim.start" layout="nodisplay"></amp-position-observer>

AMP対応後のデモページの場合は、テキスト要素の開始位置にボタンを表示するタグを挿入しているので、テキスト要素が画面上に表示される位置までスクロールするとトップに戻るボタンが表示されるようになっています。

4.スライダー

スライダーは専用のJSが用意されているのでそちらを使用します。
こちらも公式サンプルのとおりに進めれば実装できる親切設計ですが、ナビゲーションのカレント表示だけ別のJSと組み合わせて実装します。

公式サンプル

1.head内で必要なAMP用のJSを読み込みます。

<!-- スライダー(カルーセル)JSを読み込み -->
<script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script>
<!-- スライドのカレントページ数を取得するためのJS -->
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>

2.スライダーのリストをamp-carouselタグに書き換えて、属性でサイズ・レイアウト・オプションを指定します。
(Slickでは自動生成されるナビゲーションのリストも追加しておきます)

<div class="m-sec-slider">
	<amp-carousel id="mainSlide" width="960" height="564" layout="responsive" type="slides" autoplay delay="3000" loop>
		<amp-img src="./assets/img/1.jpg" alt="写真1" width="960" height="564" layout="responsive"></amp-img>
		<amp-img src="./assets/img/2.jpg" alt="写真2" width="960" height="564" layout="responsive"></amp-img>
		<amp-img src="./assets/img/3.jpg" alt="写真3" width="960" height="564" layout="responsive"></amp-img>
	</amp-carousel>
	<ul class="m-list-slideNav">
		<li class="m-list-slideNav__item"><button class="is-current"></button></li>
		<li class="m-list-slideNav__item"><button></button></li>
		<li class="m-list-slideNav__item"><button></button></li>
	</ul>
</div>

3.amp-stateタグでスライドのカレントページ数を保持する変数を設定します。記述する場所は任意です。

<amp-state id="selectedSlide">
	<script type="application/json">
		{
			"mainSlide":"0"
		}
	</script>
</amp-state>

4.amp-carouselタグにスライドのカレントページ数を取得する記述を追加します。

<!-- スライドが切り替わったら、mainSlideにスライドの番号を格納 -->
<amp-carousel id="mainSlide" width="960" height="564" layout="responsive" type="slides" autoplay delay="3000" loop [slide]="selectedSlide.mainSlide" on="slideChange:AMP.setState({selectedSlide:{mainSlide:event.index}})">

5.ナビゲーションのボタンに下記を追加します。

  • カレントページ数(mainSlideの値)が指定値と一致する場合は
    is-currentクラスを付与する記述
  • クリック(tap)で指定のスライドに移動する記述
<!--
on="tap:mainSlide.goToSlide(index=0)" => クリックで0番目のスライドに移動
[class]="selectedSlide.mainSlide == '0' ? 'is-current' : ''" => mainSlideの値が0ならばis-currentクラスを付与
-->
<ul class="m-sec-slider__nav m-list-slideNav">
	<li class="m-list-slideNav__item"><button role="button" tabindex="1" on="tap:mainSlide.goToSlide(index=0)" class="is-current" [class]="selectedSlide.mainSlide == '0' ? 'is-current' : ''"></button></li>
	<li class="m-list-slideNav__item"><button role="button" tabindex="2" on="tap:mainSlide.goToSlide(index=1)" [class]="selectedSlide.mainSlide == '1' ? 'is-current' : ''"></button></li>
	<li class="m-list-slideNav__item"><button role="button" tabindex="3" on="tap:mainSlide.goToSlide(index=2)" [class]="selectedSlide.mainSlide == '2' ? 'is-current' : ''"></button></li>
</ul>

2〜5をまとめると下記のコードになります。
あとは適宜CSSを調整して、AMP対応前の表示に近づければ実装完了です。

<amp-state id="selectedSlide">
	<script type="application/json">
		{
			"mainSlide":"0"
		}
	</script>
</amp-state>
<div class="m-sec-slider">
	<amp-carousel id="mainSlide" width="960" height="564" layout="responsive" type="slides" autoplay delay="3000" loop [slide]="selectedSlide.mainSlide" on="slideChange:AMP.setState({selectedSlide:{mainSlide:event.index}})">
		<amp-img src="./assets/img/1.jpg" alt="写真1" width="960" height="564" layout="responsive"></amp-img>
		<amp-img src="./assets/img/2.jpg" alt="写真2" width="960" height="564" layout="responsive"></amp-img>
		<amp-img src="./assets/img/3.jpg" alt="写真3" width="960" height="564" layout="responsive"></amp-img>
	</amp-carousel>
	<ul class="m-sec-slider__nav m-list-slideNav">
		<li class="m-list-slideNav__item"><button role="button" tabindex="1" on="tap:mainSlide.goToSlide(index=0)" class="is-current" [class]="selectedSlide.mainSlide == '0' ? 'is-current' : ''"></button></li>
		<li class="m-list-slideNav__item"><button role="button" tabindex="2" on="tap:mainSlide.goToSlide(index=1)" [class]="selectedSlide.mainSlide == '1' ? 'is-current' : ''"></button></li>
		<li class="m-list-slideNav__item"><button role="button" tabindex="3" on="tap:mainSlide.goToSlide(index=2)" [class]="selectedSlide.mainSlide == '2' ? 'is-current' : ''"></button></li>
	</ul>
</div>

AMP検証

要素のAMP対応は前項までで終了ですが、最後にAMPへの対応がきちんとできているかの検証を行います。
ページURLの最後に #development=1 をつけてページにアクセスします。

▼AMP対応後のデモページ(検証)
https://bulan.co/swings/demo/amp-sample/amp/#development=1

ブラウザのデベロッパーツールを開き、コンソールに「AMP validation successful.」と出ていれば対応完了です。
エラーが出た場合、原因は様々なので1つずつ根気よく解決していきます。

速度検証

AMP対応にすることによって、どのくらい表示速度の向上に繋がっているのかをPageSpeed InsightsとChromeのディベロッパーツールにあるLighthouse(Auditsタブ)で確認してみたいと思います。

参考

比較するのは下記の3ページです。

  1. AMP対応前のデモページ
    https://bulan.co/swings/demo/amp-sample/normal/
  2. AMP対応後のデモページ
    https://bulan.co/swings/demo/amp-sample/amp/
  3. AMP対応後のデモページ(キャッシュ)
    https://www.google.co.jp/amp/s/bulan.co/swings/demo/amp-sample/amp/

3番目はGoogle側に保存されたキャッシュのURLです。
モバイルかつ検索エンジンからページにアクセスすると、検索エンジン側が自動的にこのキャッシュを表示します。
これによりページの読み込み時間が短縮され、高速で表示されるようになっています。
上記仕様のため、パソコンからのアクセスや検索エンジンを経由せずにページへ直接アクセスしてもキャッシュは表示されず、AMPの恩恵をフルに受けることができないので注意が必要です。

参考

また、キャッシュを保存するためにはGoogleクローラにページを訪問してもらう必要があるので、AMP対応後のデモページをFetch as Googleでインデックス登録のリクエストをしておきました。
検索してみると無事AMPのマークが表示され、ページの表示速度も少し速くなっているうような印象です。

それでは、各ページの分析結果はこちらです。

PageSpeed Insights Lighthouse
AMP対応前 88点 約6秒(6,230ms)
AMP対応後 92点 約4秒(4,230ms)
AMP対応後(キャッシュ) 99点 約3秒(3,450ms)

Lighthouseの値は、PerformanceのTime to interactive(ページが表示されて操作できる状態になるまでの時間)の数値です。
参考までに、Lighthouseの分析結果の詳細の画像も載せておきます。

▼ AMP対応前

AMP対応前のデモページの速度検証結果

▼ AMP対応後

AMP対応後のデモページの速度検証結果

▼ AMP対応後(キャッシュ)

AMP対応後(キャッシュ)のデモページの速度検証結果

上記分析結果から、AMP対応前と対応後では明らかにパフォーマンスの改善が見られるので、効果ありと判断しても良いのではないでしょうか。
特にAMP対応後のキャッシュページは対応前のページと比べて表示速度が半分程度になっているので、これはなかなか大きいですね。
パフォーマンスの改善具合はページの内容やサーバ等も関わってくるので一概に言えませんが、AMP対応によってページの表示が速くなるということはしっかり確認することができました。

ツールやプラグインの活用

記事を書きながら改めて実感しましたが、AMPに対応するためにはそれなりの時間と手間がかかります。
とにかく早く楽に対応させたい!という場合は、変換ツールを試してみるのも1つの手です。

AMP ジェネレーターは、URLを入力して「生成する」ボタンをクリックするだけでAMPページに変換してくれます。なんて便利。
実際にAMP対応前のデモページを変換してみると、head内やimgタグなど基本的な部分を変換したHTMLが生成されました。

AMPジェネレーター変換結果の画像

さすがにスライダーやページトップボタンはJSが無効になっただけでしたが、それらの調整をする前までの細々した修正を省略できるので、かなり手間が省けるのではないでしょうか。
どこまで変換されるかは変換するページの内容によると思うので、試しに変換してみて足りない部分は調整するというやり方が良さそうですね。

また、WordPressを使用しているサイトの場合は、AMP for WordPressというプラグインを利用することでAMPに対応できます。
ただし、プラグインだけではAMPに対応しきれていない部分があり、デベロッパーツールのコンソールにエラーが出ることが多いようなので、こちらもインストール後に調整することを前提に使用した方が良さそうです。

参考

最後に

公式のAMP関連の情報は頻繁にアップデートされているようなので、この前までできなかったことが今調べたらできるようになっている!ということもあるかもしれません。
AMPを導入する際は、都度最新情報のチェックをした方が安心です。
この記事もすぐに古くなってしまうかもしれませんが、少しでも参考になれば幸いです。

Related Posts