AMP版に対応するために inline CSS を書く時のコツ

# AMP 版に対応するために inline CSS を書く時のコツ

AMP そのものに関しては、[official が詳しいのでそちらに](https://www.ampproject.org/)。

AMP が登場して一年以上経ちますが、当初考えて実装したコツが今もって役に立ちそうなので投下。

そういえば、 March 7/8 '17 に NYC で開催の [AMP Conf](https://www.ampproject.org/amp-conf-2017) に参加予定ですので、参加される方がいらっしゃいましたら、是非お声がけください。


## AMP 版作成時の課題

AMP 対応をする場合、現在では基本的には PC / SP / AMP 版それぞれを作成することになりますが、保守性を考慮すると、以下の点が特に課題になります。

1. SP / AMP 版それぞれで共通する要素の一元管理
2. CSS は inline で 50KB 以内で記載しなくてはならない

1 は、一般的になって久しい、いわゆる [Static Page Generator](https://www.staticgen.com/) を利用し、共通要素は Partial ファイル化して管理をすることで解決が可能です。フロントエンド・エンジニアが利用するもので代表的なものだと、JADE、Metalsmith、EJS、Assemble あたりでしょうか。
Partial 化に際しては、OOCSS や SMACCS、FLOCSS と言った設計ルールに則ったサイト構築が前提になるかと思います。

2 の、今回フォーカスする後者ですが… そもそも AMP 版は、 **ニュースサイトのページ表示スピードの遅さに業を煮やした有志が集まり、パフォーマンスを改善する為に考え出された** そうで、その為 AMP 版の CSS に関しても、パフォーマンスを担保する為に [CSS は　inline で 50KB 以内](https://www.ampproject.org/docs/reference/validation_errors#stylesheet-too-long)で記述する必要があり、また、[利用できる CSS にも制限](https://www.ampproject.org/docs/guides/responsive/style_pages#disallowed-styles)があります。

現在のフロントエンド開発は、様々なプロセスをタスクランナー等で自動化するのが通例ですので、

- 既存の外部 CSS ファイルの inline 化
- Unvalid な CSS の書き換えも自動化

の、二点も自動化することで、SP 版改修と共に、AMP 版も自動的に更新できるようにします。

## 保守性を担保したまま AMP 版 inline CSS を記述するには

[Addy](https://addyosmani.com/) が考案＆作成した Critical-Path CSS を活用します。

https://github.com/addyosmani/critical

Critical-Path CSS は、もともとは、**1st View に表示される要素を inline CSS として記述することで、外部 CSS の読み込みを待つことなく、且つCSS読み込み前後で二度起こる可能性がある要素の描画を一度で済ますことができる** というようなもので、
パフォーマンス最適化の為に規定の要素を描画するのに必要な CSS を inline CS として記述してくれる Critical-Path CSS の仕組みを、AMP 版で利用してしまおうというものです。

また、既存の CSS のうち、AMP html として利用不可のものは、
Critical-Path CSS を利用して inline CSS として記述した後、各タスクランナーで利用できる Replace 系のタスクで置換します。

## サンプル

[github](https://github.com/mijabi/amp-inline-css-sample)　/　[gh-pages](https://mijabi.github.io/amp-inline-css-sample/)

一年以上前なので、環境がやや古く、作りも雑ですが… [自サイトの読み物系コンテンツ](http://pulp.photo/writings/)で実装したものから、サンプルとして上のリポジトリにピックアップしました。

URL は、
通常版 http://pulp.photo/writings/161217/
に対して、
AMP 版 http://pulp.photo/writings/161217/index.amp.html
というような構成にしています。

大規模サイトで実装し、計測などを考慮するなら、AMP 専用のサブドメインを用意しても良いかもしれません。

リポジトリでは、ざっくりと以下のような処理をしています。

- Assemble でベースとなる html と 共通ファイルを Partial ファイルとして管理し、ページのユニークなデータは json ファイルとして定義
- AMP ページに必要な json-ld の中身なども、json で定義したデータを利用して記述
- amp-img タグなどは、img タグ自体を Partial ファイルとして管理し、handlebars の helper 等を利用して、SP 版と AMP 版で適宜タグ名や属性を振り分け
- 外部 CSS の inline 化

### Critical-CSS を使った CSS の inline 化

```Gruntfile.js
    critical: { // pulp.min.css から、ページで利用しているセレクタのみを inline css として記述
      dist: {
        options: {
          base: './',
          css: ['dist/css/pulp.min.css'], //  css 指定しないと必ずエラー
          extract: true,
          inline: true,
          minify: true,
          width: 320,
          height: 10000
        },
        src: '**/*.amp.html',
        dest: ''
      }

    },
```

本来 Critical は、ファーストビューで利用している CSS を外部 CSS ファイルから抜き出し、inline で記述するというもの。ファーストビューの定義は、具体的なページの幅と高さで指定しますが、ここで、ページ全体を包括する高さを指定することで、ページで利用している CSS を全て inline で書き出すことができます。

### #development=1 で出るエラーを修正

```Gruntfile.js
    'string-replace': {
      dist: {
          overwrite: true,
        files: [{
          expand: true,
          cwd: 'dist/',
          src: '**/*.amp.html',
          dest: 'dist/'
        }],
        options: {
          overwrite: true,
          replacements: [
            {
              pattern: /<style type=\"text\/css\">/g,
              replacement: '<style amp-custom>'
            }, {
              pattern: /amp=\"\"/i,
              replacement: 'amp'
            }, {
              pattern: / amp-boilerplate=\"\"/g,
              replacement: ' amp-boilerplate'
            }, {
              pattern: /@charset \"UTF-8\";/g,
              replacement: ''
            }, {
              pattern: /@-ms-viewport{width:device-width}/g,
              replacement: ''
            }, {
              pattern: /@viewport{width:device-width}/g,
              replacement: ''
            }, {
              pattern: /!important/g,
              replacement: ''
            }
          ]
        }
      }
```

AMP として作成したページの URL 末尾に、#development=1 を記述することで、ブラウザのエラーコンソール上で、バリデート結果を表示することができます。

inline CSS に関するエラーは Critical-CSS で inline CSS を書き出した後で、string-replace タスクを利用して置換します。
サンプルでは、カスタム CSS を記述する為の属性 ```<style amp-custom>``` への置換や、Bootstrap v4 で出るエラーの置換もしています。

---

細かい点は[サンプル](https://github.com/mijabi/amp-inline-css-sample)をご覧いただければ…