そもそもMiddleman使ったこと無くて 静的HTML書き出しは都度簡単なスクリプトを書いてて、とはいえ、Mojolicious::Liteアプリを一枚立ち上げとけばいいよな、なんて思ってたら、GitHub Pages使う時なんか便利だよねーと思っている今日このごろです。で、15日のAdvent Calendarでmozquitoさんが「MojoliciousでMiddleman的(静的HTML書き出し)なことをする」というエントリーを書いてて
あーなるほどこういうMojoliciousの使い方あるんだー
と非常に面白かったです。で、もうちょっと簡単に、例えば「Mojoliciousのテンプレート機能だけ使いたいんだよ!」とわりきって使う方法があるかなーと考えてみました。各種設定は、Mojolicious::Plugin::Configを使うもしくは、テンプレート内でstashを経由して引き回すことを想定しています。今回はあまりディレクトリ切らずに
$ mojo generate app MyApp
としてアプリケーションをつくりました。そこにRoutingの定義を書きます。これは存在して欲しいHTMLファイルをベターと書けばOKです。root#index とありますが Root コントローラーはつくらないで auto_rendering を効かせてそのままテンプレートをレンダリングします。
package MyApp;
use Mojo::Base 'Mojolicious';
sub startup {
    my $self = shift;
    my $r = $self->routes;
    $r->get('/index.html')->to('root#index');
    $r->get('/about.html')->to('root#about');
    $r->get('/news.html')->to('root#news');
}
1;
静的ページなので .html と拡張子を付けておきます。あとはmozquitoさんのスクリプトをヒントにしてスクリプトを書きます。この際に明示的に Mojolicious::Routes の chiildren メソッドを呼び出し Mojolicious::Routes::Route の一覧を取得。render メソッドでパスを取得しています。この場合だと
- /index.html
- /about.html
- /news.html
になります。それをそのまま Path::Tiny に食わせて public ディレクトリに書き出しています。この辺はまぁー各自の環境によってよしなに。
use strict;
use warnings;
use Mojo::UserAgent;
use Path::Tiny;
use MyApp;
my $ua = Mojo::UserAgent->new();
$ua->server->app( MyApp->new );
my $routes = $ua->server->app->routes();
for my $r ( @{ $routes->children() } ) {
    my $path = $r->pattern->render();
    my $tx = $ua->get($path);
    next if $tx->error;
    my $html = $tx->res->text;
    print "Redering $path ...\n";
    path('public')->child($path)->spew_utf8($html);
}
個人的にはMojoliciousのテンプレート周りは使い勝手が非常によいのでそれでスタティックサイトをつくれるとなるとなかなか便利じゃね!って思ったのでmozquitoさんのアイデアと実装に感謝ですね。