Posted at

RailsアプリのAMP対応をSassで快適に

More than 3 years have passed since last update.


AMPとは

AMP(Accelerated Mobile Pages)はモバイルでのウェブページ表示を高速化する手法です。Googleが強く推奨しており、2016年10月よりGoogleのモバイル検索結果の表示にAMPが使用されるようになりました。

高速化のため、AMPページで用いられるHTMLには独自のプロパティや制限があります。cssに関しても、外部ファイルを読み込めない等の制限があります。


RailsでAMP対応する際の問題

AMPでは外部ファイルを読み込めないので、cssをheadタグ内のstyleタグに書かなければなりません。すなわち、ビュー内でcssをrenderする必要があります。しかし、アセットパイプラインにはそんな仕組みはありません。File.readでcssファイルを読み込んでビューに書き出すといった方法はすぐに考え付きますが、これではコンパイルが必要なSassは使えません。


RailsのビューでSassをrenderする

ではどうやってRailsのビューでSassをrenderするか。答えはSassのgemを直接使うです。なかなか使う機会はないと思いますが、Sassのgemはファイル読込・プリコンパイル・圧縮を一括で行ってくれるスグレモノです。しかも、ワンライナーで書けます!(以下のサンプルでは見やすくするために改行を入れてあります)

 以下にサンプルを示します。プリコンパイルと圧縮の処理はヘルパーにまとめ、それをビューで呼び出す形にしています。


/app/helpers/application_helper.rb

def render_css(path)

raw Sass::Engine.for_file("#{Rails.root}/app/assets/stylesheets/#{path}", {
load_paths: ["#{Rails.root}/app/assets/stylesheets"],
style: :compressed
}).to_css
end



/app/views/abc/amp.html.slim


style amp-custom=true
= render_css('abc/amp.sass')


通常のstylesheet_link_tagと同様に使えるようにパス周りを工夫しています。拡張子は必須ですが、Sass::Engine.for_fileが拡張子でフォーマットを判断してくれるので、scssやcssの場合も対応できます。


簡単な解説


Sass::Engine.for_file

Sass::Engine.for_file(filename, options)は、第一引数にコンパイルしたいファイルのパス、第二引数にコンパイルのオプションをとります。このメソッドはファイルパスに対応したSass::Engineのインスタンスを生成して返します。このインスタンスはto_cssrenderといったメソッドを持っており、これらを呼び出すことでコンパイル結果のcssを取得できます。


Sass::Engine.for_fileのオプション

 load_pathsでSassの@importの基準パスを指定できます。上のサンプルでは"#{Rails.root}/app/assets/stylesheets"を指定して、通常のアセットパイプラインと同様に@importを使えるようにしています。また、styleにcompressedを指定することで圧縮が有効になります。


render_cssの戻り値

前述のto_cssの結果をそのまま返してしまうと、ビューでcssがhtmlエスケープされてしまいます。

それを防ぐためにrawメソッドを用い、その戻り値を返すようにしています。


まとめ

たった一行のヘルパーで、AMPページをSassで快適に実装できるようになります。これからAMPに関わる方々のお役に立てれば幸いです。


出典

https://www.ampproject.org/learn/about-amp/

https://japan.googleblog.com/2016/10/amp-1.html

http://sass-lang.com/documentation/Sass/Engine.html