MojoliciousでSassを使う
今MojoliciousでCGIゲームの三国志NETの改造版だったものをぼちぼち作りなおしているんですが、css書いている時にやっぱりSass使いたいなー、と思って色々調べてみました。
環境
Ubuntu 14.04
perl 5.22.2
Mojolicious 7.00
Mojolicious::Plugin::AssetPack 1.17
CSS::Sass 3.3.0
どんなモジュールがあるか
早くMojoliciousでSassを使う方法を知りたい人はここは飛ばした方がいいです。
CPANやgithubを軽く調べた感じだと、MojoliciousでSassを使うには以下のモジュールが
・Mojolicious::Plugin::AssetPack
・Mojolicious::Plugin::Sass
・Mojolicious::Plugin::SassRenderer
更にPlackのモジュールが
・Plack::Middleware::File::Sass
Mojolicious::Plugin::AssetPack
唯一今でも活発に開発&メンテが続いているモジュールでした。
仕組みとしては CSS::Sass もしくはRubyのgemからSassをインストールしたものを使ってコンパイルしているようです。
別ファイルに記述したSassファイルをサーバー立ち上げ時にコンパイルする、といったプラグインのようです。
ちなみにこのプラグインでCoffeeScriptやlessなども使えるそうです。
Mojolicious::Plugin::Sass
Text::Sassをつかって、テンプレートの中に記述したSassをコンパイルするプラグインのようです。
しかし別ファイルに記述したSassファイルはコンパイルしてくれませんし、何よりも Text::Sass はSassの実装がちゃんとできていないのでSassの機能のいくつかが使用できません。(import,extendが使えないなど...)
Mojolicious::Plugin::SassRenderer
5年近く更新されていませんでした。また、これもText::Sassを使っているのでボツですね...
Plack::Middleware::File::Sass
これも何年も更新されてなく、Text::Sassを使っていてますし、そもそも僕はPlackで立ち上げていないのでボツですね...
というわけで、各モジュールを調べた結果Mojolicious::Plugin::AssetPack一択となりました。
ですがMojolicious::Plugin::AssetPackではちょっとテンプレートの中にSassを記述したい時などには使えないようなので、テンプレートの中でSassを記述するプラグインは別途自作してしまうことにしました。
1.別ファイルにSassを記述するとき→Mojolicious::Plugin::AssetPackを使う
1.CSS::Sass、Mojolicious::Plugin::AssetPackをインストールする
cpanm CSS::Sass
cpanm Mojolicious::Plugin::AssetPack
でCSS::Sass、Mojolicious::Plugin::AssetPackをインストール。
ちなみに僕の環境ではMojolicious::Plugin::AssetPackのインストール時にテストにこけてインストールに失敗したので、--forceオプションをつけてインストールしなおしました。
2.基本的な使い方
※Sassファイルはプロジェクトディレクトリ内のassetsディレクトリ内に置きます。
$self->plugin('AssetPack' => {pipes => [qw/Css Sass/]});
$self->asset->process('base.css' => ('scss/base.scss'));
%= asset 'base.css'
これでサーバーを立ち上げるたびに(変更があれば)別ファイルに記述したsassファイルをコンパイルし、できたcssファイルを読み込んでくれるようになります。
他にも色々できます、詳しくはドキュメントを読むべし!
2.テンプレートの中に直接Sassを記述したい場合→CSS::Sassを使った自作プラグインで
なかなかいい感じの Mojolicious::Plugin::AssetPack ですが、テンプレートの中に直接記述したSassの面倒までは見てくれません。
他のSass関係のモジュールは未完成の Text::Sass を使用しているため満足に記述できません。
なので CSS::Sass を使って簡単にテンプレートの中のSassコードをコンパイルしてくれるプラグインを作ってみました。
コードはこんなかんじです:
package Mojolicious::Plugin::InnerSass {
use Mojo::Base 'Mojolicious::Plugin'; # Mojolicious::Plugin を継承
use Mojo::Cache; # キャッシュに使用
use CSS::Sass; # Sass,Scssコンパイラ
has 'sass' => sub { CSS::Sass->new( output_style => CSS::Sass::SASS_STYLE_EXPANDED() ) };
has 'cache' => sub { Mojo::Cache->new(max_keys => 200) };
sub register {
my ($self, $app, $conf) = @_;
$app->helper(sass_to_css => sub {
my ($c, $sass, $conf) = @_;
my $route = $c->current_route();
my $cache = $self->cache->get($route) // '';
if ($cache) {
$app->log->debug('Loading sass data...');
return $cache;
} else {
my $compile_sass = $self->sass->compile($sass);
$self->cache->set($route => $compile_sass) if $conf;
return $compile_sass;
}
});
}
}
1;
%= stylesheet begin
<% my $sass = ' # sassコードを変数に格納
$red:'.$config->{'color'}{'red'}.';
.red {
color: $red;
}
'; %>
%== sass_to_css($sass, 1); #sassコードをcssに変換、キャッシュする、返却値はXMLエスケープせずに出力
%= end
プラグインのファイルは/lib/Mojolicious/Plugin
に置いて、あとは Myapp.pm で読みこめばテンプレートでSass,Scssが記述できるようになります。
一度コンパイルしたものはメモリに保存しているので、初回以外は処理時間がかかるということもありません。
まあ処理時間がかなりかかるほど大きいコードなら別ファイルに分けた方がいいですし、主に開発時に使用する用のプラグインになりますが。
テンプレート側の記述もちょっと気持ち悪いですけど、個人で使う分だしこんなもんでいいかなあと。