とあるシンプルな既存ページのAMP対応をした時のメモ

# はじめに
- AMPプロジェクトは現在進行系で開発中なので、仕様が追加・変更されることがあります。
- いたってシンプルなページのAMP対応だったので、AMPタグもAMP JSライブラリもほぼ使っていません。
- 主に、CSSをこねくりまわしたお話です。
- Gruntが主役です


# AMP（アンプ）
- Accelerated Mobile Pages
- モバイル端末でのWebページの表示を高速化するためのプロジェクト
- 通常版HTMLと別にAMP版HTMLを作成し、それぞれを関連付け
- HTML5をベースに、いくつかの制約を設けた AMP HTMLや AMP JS を使って実装
    - 一部HTMLタグの置き換え、インラインCSS、AMP JS以外のJS禁止、など

詳しい概要や現時点での動向は、公式サイトや[海外SEO情報ブログ](https://www.suzukikenichi.com/blog/)をチェック！


## 実装前にやること
- JSで実装されている部分の代替（AMP JSライブラリ）、削除などを検討
- 他、構成要素の整理
- 必要に応じて、UIやデザインの調整

■参考サイト
- [Accelerated Mobile Pages Project](https://www.ampproject.org/ja/)
- [AMP 対応のトップニュース  \|  Structured Data  \|  Google Developers](https://developers.google.com/structured-data/carousels/top-stories)
- [amphtml/extensions at master · ampproject/amphtml](https://github.com/ampproject/amphtml/tree/master/extensions#amp-html-extensions)
- [AMP by Example](https://ampbyexample.com/)


# 構造化データ
- リッチスニペット（リッチカード）を導入するために必要
- schema.org + JSON-LD の組み合わせ（Google推奨）
    - JSON-LDのメリット：Microdata、RDFaと違ってどこにでも記述でき、DOMに変更を加えることがない

■参考サイト
- [Google、リッチスニペットよりもさらにビジュアルな"リッチカード"をモバイル検索に導入 \| 海外SEO情報ブログ](https://www.suzukikenichi.com/blog/google-rich-cards/)
- [Schemas \- schema\.org](https://schema.org/docs/schemas.html)
- [Recipes  \|  Search  \|  Google Developers](https://developers.google.com/search/docs/data-types/recipes)


# Google CDNのAMPキャッシュ
- AMP版ページはGoogleのサーバーにキャッシュされている（ゆえに高速）
- ユーザーが閲覧する限り、AMPキャッシュは自動で更新される

## キャッシュを確認（強制更新）するには
自分でAMPキャッシュのURLにアクセスする

```
httpsの場合：https://cdn.ampproject.org/c/s/hogehoge
httpの場合：https://cdn.ampproject.org/c/hogehoge
※hogehoge=確認したいURLからプロトコルを省いたもの
```

```閲覧中AMPページのキャッシュURLにアクセスするブックマークレット
javascript:(function(){var protocol=window.location.protocol;protocol=protocol.substr(0,(protocol.length-1));var cdnURL='https://cdn.ampproject.org/c/';switch(protocol){case 'http':window.open(location.href.replace(protocol+'://',cdnURL));break;case 'https':window.open(location.href.replace(protocol+'://',cdnURL+'s/'));break;}})();
```

■参考サイト
- [AMPページがAMP CDNにキャッシュされているかどうかを調べる方法 \| 海外SEO情報ブログ](https://www.suzukikenichi.com/blog/how-to-see-your-amp-pages-cached-on-amp-cdn/)
- [Google CDNのAMPキャッシュを大解剖――URLフォーマット、更新プロセス、更新方法、削除方法 \| 海外SEO情報ブログ](https://www.suzukikenichi.com/blog/anatomy-of-amp-cache/)


# 開発中の検証やバリデート

## ローカルで可
- URLの末尾に #development=1 を付加して、Chromeのコンソールを利用
    - `http://localhost:8000/released.amp.html#development=1`
- [AMP Validator \- Chrome ウェブストア](https://chrome.google.com/webstore/detail/amp-validator/nmoffdblmcmgeicmolmhobpoocbbmknc?hl=ja)

```下記参考ブックマークレットの改良版（別タブでなく同タブ展開にしただけ）
javascript:(function(){if(document.getElementsByTagName("html")[0].hasAttribute("⚡")||document.getElementsByTagName("html")[0].hasAttribute("amp")){window.location.href=location.href+"#development=1";location.reload()}else{if(document.querySelectorAll("link[rel='amphtml']").length){window.location.href=document.querySelectorAll("link[rel='amphtml']")[0].href+"#development=1"}else{alert("AMP%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82")}}})()
```

■参考サイト
- [AMPページに＃development=1を付けて開くブックマークレット \| q\-Az](https://q-az.net/amp-development/)


## オンライン
- [The AMP Validator](https://validator.ampproject.org/)
- [Google Search Console AMP テスト](https://search.google.com/search-console/amp)
- [構造化データ テストツール](https://search.google.com/structured-data/testing-tool/u/0/)
- [JSONLint \- The JSON Validator\.](http://jsonlint.com/#)


# AMP版HTMLビルドのフロー
※あくまでも今回やった対応の話なので、サイト構造やページ構成、開発環境によって色々あると思います。
※既存ページ（通常版）のAMP版HTMLを、できるだけ自動化してつくりたかった…。

## CSSなしのAMP版HTMLをビルド
一旦、CSSを無視して、AMP用に調整したHTMLをビルド。
[amphtml/amp\-html\-format\.md at master · ampproject/amphtml](https://github.com/ampproject/amphtml/blob/master/spec/amp-html-format.md)

※2016/11/01時点。最新情報は常に要確認。

| タグ | AMP HTML |
| --- | --- |
| script | application/ld+json以外NG |
| img, video, audio, iframe | AMPタグに置き換え |
| img | AMP HTMLではsrc、width、height属性の数値指定が必須（空だとエラー）またlayout属性にresponsiveを指定すると、アスペクト比を保ったまま、画面幅に合わせて画像が拡大、縮小することができます。 |
| frame, frameset, object, param, applet, embed, form, input elements | NG（buttonはOK）formは将来的にサポート予定→ついさきほど、formの正式対応が発表されたという記事を見たので、近々対応。 |
| style | headタグ内OK、amp-custom属性が必要 |
| link | canonical以外NG。stylesheetとpreconnect、prerender、prefetchの値は許可しない。例外としてWebフォントの読み込みは使用可能 |
| meta | http-equivのみNG |
| a | href属性にjavascript:から始まる値を指定するのは禁止。target属性を指定する場合は_blankのみ設定可能。それ以外は制限なし。 |
| svg | ほとんどOK |

## ページで必要なCSSの抽出とインライン化
通常版のCSSをそのままインラインCSSとして読み込むとAMP仕様の容量オーバー（50KB）になるので、必要なセレクタだけ抽出したかった。

[grunt\-critical](https://www.npmjs.com/package/grunt-critical)を使用。
ページで必要なCSSセレクタのみを抽出し、インラインCSSとしてHTMLに書き出す。

※criticalの注意点
- 仕様？で、値がないHTML属性に勝手に`=“”`を付けてくるので、下記AMPバリデートエラーの一因
- 読み込み元CSSの画像パスが相対パスでもルートパスに変更してくる

## バリデートエラーを解消
[grunt\-string\-replace](https://www.npmjs.com/package/grunt-string-replace)を使用して置換。
HTML, CSSのバリデートエラーを解消して`AMP validation successful.`にする。

■HTML
criticalによって付与される余計な記述を削除
[amphtml/amp\-html\-format\.md at master · ampproject/amphtml](https://github.com/ampproject/amphtml/blob/master/spec/amp-html-format.md)

```
<html amp="" lang="ja"> -> <html amp lang="ja">
<style amp-boilerplate=""> -> <style amp-boilerplate>
```

■CSS
[Supported CSS | AMP](https://www.ampproject.org/docs/guides/responsive/style_pages)

```
<style type="text/css"> -> <style amp-custom>
@charset "UTF-8"; -> 削除
!important -> 削除
```

※2016/11/01時点。最新情報は常に要確認。
- インラインCSSの容量上限は50KB
- !important, *,  :not(), filterの使用禁止
- amp-で始まる要素に疑似要素の使用禁止（CSSは使用可能）

## その他の調整
一部HTMLのタグやCSSの記述が変わることになり、ページの内容や構造によってはCSSが適用されなくなったりレイアウトが崩れるので、別途調整します。


# 起こった問題と解決・回避策
CSSばかり

## ローカルにファイルがないCSSを抽出できなかった
criticalは、Gruntfile.jsで指定している（ローカルに存在する）ファイルからCSSを抽出するため、サーバー上にあるファイルからCSSを抽出できず、困った（通常版サイトの仕様）
↓↓↓
[grunt-curl](https://github.com/twolfson/grunt-curl)でファイルをダウンロードしてローカルに配置


## 今度は背景画像が表示されない
criticalのオプション `maxImageFileSize` のデフォルト値を超えていたので表示されず。
↓↓↓
オプションの値を変更
`maxImageFileSize: 100000`

## なんかCSSの記述が微妙に足りない
HTMLから静的に抽出されるので、動的に出し分けされる部分のパターンが抽出できない。
↓↓↓
HTMLに全パターン出した状態でrunさせる

## CSSの記述がまだ足りない
要素に直接指定しているCSSが抽出されていなかった（具体的にはimg）
criticalをrunさせる前にAMPタグに書き換えていたため。
↓↓↓
criticalがrunした後にAMPタグへの書き換えを行う。インラインCSSも同様。

`img -> amp-img`

他、minifyによってなぜか記述が消えたり、画像パスが変わったりしたものを
grunt-string-replace で調整。


## CSSがまだおかしい
元CSSの!importantが原因。!important強い。
↓↓↓
AMP調整用のCSSを追加

## そして、インラインCSSの容量が仕様の倍以上へ
DATA-URIによる背景（しかもスプライト）画像の埋め込みが主な原因。
↓↓↓
DATA-URIの背景を画像読み込みに変更


## AMP validation successful.
![amp.png](https://qiita-image-store.s3.amazonaws.com/0/5753/0d1d34ce-792b-337c-f7f7-665ef12a7d87.png)


# まとめ
- 結局、CSSの調整に一番苦労した。
- 次は、もう少しシンプルではないページでAMPタグやAMP JSライブラリを使ってみたい