AMP のペライチを作って Google 検索結果に AMP マークをつけるまで

AMP のビルド・コーディング・配信と、もろもろ注意点などを書き残しておく。

## 成果物

父親が趣味で作っている「あかりひょうたん」を宣伝するページを作った。

- [https://shutan.work](https://shutan.work)
- https://github.com/macoshita/shutan.work
- [Google 検索結果](https://www.google.co.jp/search?q=%E3%81%B2%E3%82%87%E3%81%86%E3%81%9F%E3%82%93+shutan)
    - モバイルブラウザで見ると AMP マーク :zap: が付いてるはず

## 構成

- AMP のみ。通常のページは作っていない
- Firebase Hosting を使って配信

## ビルド

AMP は **CSS をインラインで書かなければならない**。  head に `<style amp-custom>` を使って書く。
それを満たしつつ「楽したい」「サイトパフォーマンス」を考慮して、ビルド環境は下記を抑えることにした:

- CSS
    - autoprefixer
    - minify
    - import
        - normalize.css を埋め込みたい
- HTML
    - 上記のCSSを埋め込む仕組み
- Cache Busting
    - 画像のファイル名にハッシュ値を含めて長期キャッシュ
- ファイルを変更したら自動ビルド・リロード

これらを満たすために、下記のような戦略を取った:

- CSS
    - postcss とそのプラグインを使ってビルドする
    - autoprefix をやるついでに [cssnext](http://cssnext.io/) を導入。変数や nesting なんかもできるようになる
- HTML
    - [pug](https://pugjs.org/) で書き、生成した CSS  を [include](https://pugjs.org/language/includes.html) する
- Cache Busting
    - [gulp-rev](https://github.com/sindresorhus/gulp-rev) で画像ファイルにハッシュ値をつけて、 [gulp-rev-replace](https://github.com/jamesknelson/gulp-rev-replace) で pug から生成した HTML の画像パスを書き換える
- 自動ビルド・リロード
    - gulp.watch で監視してビルドして browsersync でリロード

ビルド手順をまとめると以下となる:

1. dist をクリア
2. static を dist に コピー
3. assets/img の画像をハッシュ値付けながら dist にコピー
4. src/main.css を postcss 通して tmp/main.css にビルド
5. src/index.pug を html にビルド
    - この時 pug の include によって tmp/main.css が HTML に埋め込まれる
6. html 内の画像ファイル名をハッシュつきの名前に置換し、 dist/index.html にビルド
    - CSS がインラインだから、 CSS 内で `url()` で指定してあるところもここで書き換わる

あまり AMP のビルド環境については情報がないので、素直に gulp で自作した。まぁ大体こんな感じになるんじゃないかと思う。

## 開発

### はじめに

- [AMP Project](https://www.ampproject.org/) の Getting Start から始めて、読みつつ書きつつ進めた
    - よくあることだけど日本語ドキュメントは古いので基本参考にしないのがよい
    - ここが起点なので、困った時は基本ここをみるのがよい。関連プロジェクトへのリンクもある。
    - ここから [AMP By Example](https://ampbyexample.com/) などにリンクがある。
- [Layout & media queries](https://www.ampproject.org/docs/guides/responsive/control_layout) を読むとレスポンシブにするのに役立つ
    - といっても普通に CSS で media queries が書けるので、 media 属性とかはあまり使ってない

### バリデーション

- `#development=1` を付けて Chrome でアクセスすると、 DevTools のコンソールに AMP バリデーションチェック結果が表示されるので、それをちょくちょく確認
    - ただ、 browsersync がリロードのためにスクリプトを埋め込むので、そこだけバリデーションコケる。多分許容するしかないと思う。
- [AMPBench](https://ampbench.appspot.com/) も通す
    - 自分の場合は [ngrok](https://ngrok.com/) を使ってデプロイ前に通してた
    - AMP バリデーションだけじゃなくて、 robots.txt とかも見てくれる

### 工夫した所

- 明るいところで撮ったひょうたんと暗いところで撮ったひょうたんをスクロールに合わせて切り替え
    - [amp-fx-flying-carpet](https://ampbyexample.com/components/amp-fx-flying-carpet/) を2つ並べて実現してる
        - あまりデザインが得意じゃないので、こういうパーツがそろってるのは嬉しいけど、気をつけないとグッチャグチャになりそう
- Google Fonts でロゴを書いてるんだけど、下記の prefetch とかの書き方をどこで見かけたか思い出せない。 AMP 公式っぽいページで見かけた気がするんだが……。

    ```html
<link href="https://fonts.gstatic.com" rel="preconnect">
<link href="https://fonts.gstatic.com" rel="dns-prefetch">
    ```

### 細かい所

AMP のコンポーネント諸々、あまり PC で表示することを想定してない気がする。例えば:

- amp-img で object-fit を使うように書いてあるけど、 IE 11 非対応、 Edge 16 でようやく対応（今は Edge 15）
    - ヘッダの背景画像とかは background-image でやってる
- amp-image-lightbox 拡大した画像をクリックで閉じられない
    - スマホだとスワイプで閉じるようになってる。とりあえず構わず使っちゃってるけど、PCではイマイチだろうなと思う。

## デプロイ

[Firebase Hosting](https://firebase.google.com/docs/hosting/) を使った。

- firebase CLI をインストール
- firebase init してデプロイ先を設定
- firebase deploy

これだけで静的ファイルのホスティングが可能。ドキュメントがすごくシンプルなので詳しくは端折るけど、下記が無料でできる。

- 独自ドメインを連携でき、勝手にそのドメインの証明書を取得して SSL で配信してくれる
- firebase.json でデプロイ元のディレクトリや Content-Type 等の設定を細かく行える
- 10 GB/月までの転送
- 連携したドメインは Search Console で確認済み扱いになる（プロパティ追加するだけで直ぐにサチコンが使えるようになる）

最初は GitHub Pages とか S3 とか考えてたけど SSL 設定とデプロイが楽すぎてこっちにした。これは推せる。

## Google 検索結果で AMP マークを付けるためにどうしたか

Firebase Hosting を試そうと思って適当に上げてみたところ、 Google 検索結果で「AMPエラーが検出されました」と表示されてしまい、このエラーを消すために色々調べた。

- いろんな検索ワードで試してみる
    - マークが出たり出なかったりすることがわかった
- [AMPBench](https://ampbench.appspot.com/) を通した
    - ドメインが appspot だけど、 ampproject.org からリンクが貼られている
    - 問題なし
- Search Console で AMP エラーを確認
    - バリデーション通ってるのに「CSS にエラーがある」と言われ続け、 バリデーションにバグがあるではと疑うなどして無駄な時間を使った
- [キャッシュのアップデートをリクエスト](https://developers.google.com/amp/cache/update-cache)
    - update-ping の方をとりあえず行って、1日くらい待ったがダメだった
- キャッシュアップデート、証明書を使う方法

一応時系列としては、証明書を使う方法を最後に実施し、その翌日にエラーが消え、雷マークが付くようになった。
ただまぁ、ほっといてもそのうち直った可能性は高いし、もしかしたらキャッシュのアップデートとか関係なかったのかもしれないので何とも言えない。今後何かあったら下記で対応かなと思ってる。

1. 一番大事なのは **バリデーションが通っているかどうか** なので、まずそこを確認する
2. 通っているのにエラーが出続けるような状況なら、 update-ping を実行して待つ
3. それでもなかなか変わらないなら update-cache を試す

なお、証明書を使うアップデートの手順は下記:

- RSA キーを作る
- 公開鍵を `/.well-known/amphtml/apikey.pub` に配置
    - `Content-Type: text-plain` にする
- リクエストする URL を署名し、リクエストパラメータに含めて送信
- OK の文字列が 204 で返ってくれば成功

具体的なやり方は AMP のドキュメントと GitHub に置いてある [雑なシェルスクリプト](https://github.com/macoshita/shutan.work/blob/master/update-amp-cache.sh) を見ればなんとなく伝わると思う。

てか Search Console でプロパティ追加する前からインデックスされると思わなかった。 Firebase だからなのか？

## まとめ

AMP を書くこと自体は、手軽にバリデーション出来るし、そんなに苦がない。
けど問題は Google 検索結果に AMP マークが付かないとなってからで、「ドキュメントに見落としがあるんじゃないか」「 validator バグってんじゃないのか」とか色々可能性を考えてしまい面倒だった。
仮に AMP マークつかなくても別にサイトが見れないわけではないので、 validator を信じて待つのがよい（と思う）。

ちなみに、 AMP にしたからとって PageSpeed Insights で高得点が取れるわけではない。実際このサイトはそんなに得点が高くない。 Google 検索結果以外からもやってくることを考えると、画像の圧縮や長期キャッシュなどは基本として抑えておくべきだろう。

余談だけど、ひょうたんのページはとても喜んでもらえたので、嬉しかった。そんなエンジニア10年目。