Ruby
RubyOnRails
AMP

RailsでAMP化するときにエラーがでたらgemも疑う

RailsサイトのAMP化をしていたところ、ルーティング等の面倒くさい設定が完了し、まずはとりあえず「AMP HTML」のサンプルと同じAMPページを作って出力してみたら、サンプルと同じはずなのにAMPバリデートエラーが生じてしまいました。

調査するとRailsでAMP化するとき特有ともいえる、gemによって発生していたものでしたので、内容と対処法をまとめておきます。

AMP HTMLサンプルテンプレート

https://www.ampproject.org/ja/docs/reference/spec#sample-document
こちらのAMPプロジェクト公式のAMP HTMLサンプルテンプレートを利用して、とりあえずAMPページとして出力しようとしておりました。
※ややこしい amp-imgタグと amp-adタグの部分は削除してあります。

<!doctype html>
<html >
  <head>
    <meta charset="utf-8">
    <title>Sample document</title>
    <link rel="canonical" href="./regular-html-version.html">
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
    <style amp-custom>
      h1 {color: red}
    </style>
    <script type="application/ld+json">
    {
      "@context": "http://schema.org",
      "@type": "NewsArticle",
      "headline": "Article headline",
      "image": [
        "thumbnail1.jpg"
      ],
      "datePublished": "2015-02-05T08:00:00+08:00"
    }
    </script>
    <script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script>
    <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>
    <script async src="https://cdn.ampproject.org/v0.js"></script>
  </head>
  <body>
    <h1>Sample document</h1>
    <p>
      Some text
    </p>
  </body>
</html>

AMPに必須なものだけの、本当にミニマムなAMP HTMLです。

サンプル通りなのにバリデートエラー

表示されているページが、ちゃんとAMP HTMLになっているかどうかをチェックするAMPバリデーターはChrome DevToolに標準で搭載されています。

URL末尾に #development=1 をつけてページを開き、Chrome DevToolのConsoleで確認できます。

するとサンプルテンプレート通りに作ったにも関わらずエラーが発生しました。

1.png

Only AMP runtime 'script' tags are allowed, and only in the document head

とあります。

AMPでは、AMP提供のものと「application/ld+json」形式以外のJavaScriptは使用できないことになっています。
それを守っていないよというエラーだと思うのですが、ただサンプルテンプレートのコピペしただけなのになぜ?

出力ページのページソースを直接確認

いつものブラウザの「ページのソースを表示」から。

<!doctype html>
<html >
  <head>
    <meta charset="utf-8">
    <title>Sample document</title>
    <link rel="canonical" href="./regular-html-version.html">
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
    <style amp-custom>
      h1 {color: red}
    </style>
    <script type="application/ld+json">
    {
      "@context": "http://schema.org",
      "@type": "NewsArticle",
      "headline": "Article headline",
      "image": [
        "thumbnail1.jpg"
      ],
      "datePublished": "2015-02-05T08:00:00+08:00"
    }
    </script>
    <script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script>
    <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>
    <script async src="https://cdn.ampproject.org/v0.js"></script>
  </head>
  <body>
    <h1>Sample document</h1>
    <p>
      Some text
    </p>
  <script async type="text/javascript" id="mini-profiler" src="/mini-profiler-resources/includes.js?v=9db1f8db18400644bd5c7449e5295620" data-version="9db1f8db18400644bd5c7449e5295620" data-path="/mini-profiler-resources/" data-current-id="do6ge3kdg5exsbbphsap" data-ids="do6ge3kdg5exsbbphsap,fc9hgke1ptxn3vb0sviy,tepcmq0wjhn0njfwofu5,kpd5c9tum1022gh3vo4,75ocdzxnyt0phb1mo7mi,s5ijv1gq9e5yu1iewe5p,135tooj4i31nt4l9nlzq,7tuev8odugmnmahar4tt,rjwiec8j6yxqa8flhv6t,1guinsgu8i3ej963avbr" data-position="left" data-trivial="false" data-children="false" data-max-traces="10" data-controls="false" data-authorized="true" data-toggle-shortcut="Alt+P" data-start-hidden="true"></script>
</body>
</html>

</body> の直前に知らないscriptタグがある。

<script async type="text/javascript" id="mini-profiler" src="/mini-profiler-resources/includes.js?v=9db1f8db18400644bd5c7449e5295620" data-version="9db1f8db18400644bd5c7449e5295620" data-path="/mini-profiler-resources/" data-current-id="do6ge3kdg5exsbbphsap" data-ids="do6ge3kdg5exsbbphsap,fc9hgke1ptxn3vb0sviy,tepcmq0wjhn0njfwofu5,kpd5c9tum1022gh3vo4,75ocdzxnyt0phb1mo7mi,s5ijv1gq9e5yu1iewe5p,135tooj4i31nt4l9nlzq,7tuev8odugmnmahar4tt,rjwiec8j6yxqa8flhv6t,1guinsgu8i3ej963avbr" data-position="left" data-trivial="false" data-children="false" data-max-traces="10" data-controls="false" data-authorized="true" data-toggle-shortcut="Alt+P" data-start-hidden="true"></script>

これがどこからやってきたのかというと、正体は rack-mini-profiler というViewのレンダリングやDBクエリのパフォーマンスを計測して表示してくれるgemが発行しているものだった。

2.png

こんな感じで計測時間をブラウザの左上に表示してくれる、普段は便利なやつです。

対策

gemをOFFにしたりマスキング的なことしないとかなと思いましたが、幸い rack-mini-profiler はURL操作のみで計測結果を表示しないようにすることができました。

URLにパラメータ?pp=disableをつけるだけで、同一セッション内で計測結果が常に表示されなくなり、今回のエラー対象のスクリプトも発行されなくなります。

http://hoge.com/articles/1.amp?pp=disable

再度、計測結果を表示するようにするためには、URLにパラメータ?pp=enableをつければ大丈夫です。

結果

Consoleで確認するとエラーが消え、AMP validation successful.と表示され、無事にAMPページとして認識されました。

3.png

まとめ

AMPではJavaScriptやCSSの使用に制限があります。
Railsのgemのなかには、gem側でJavaScriptやCSSを発行するものも存在するので、AMP対応には注意が必要です。

今回は rack-mini-profiler というgemが対象でしたが、有名どころだとN+1問題を検出し表示してくれる bullet なんかも同じことが起きると思います。

本番環境では起きなかったりするものも多いかと思いますが、適宜gemの無効化や設定変更がAMP対応には必要になってきそうです。