MojoliciousでCSSなどの静的ファイルを利用する

今回は静的ファイルを利用したWebアプリケーションを作成してみましょう。静的ファイルはスクリプトのあるディレクトリのpublicというディレクトリに配置します。cssというディテクトリを作成して、その中にcommon.cssというファイルを配置します。

# ディレクトリ構成
app.cgi
public/css/common.css

以下がCSSを読み込んだスクリプトです。見出しの部分が赤くなっているのが確認できると思います。

stylesheet関数を利用して、CSSを読み込んでいます。

#!/usr/bin/perl

# Mojoliciousを読み込むためのライブラリのパスの設定
use FindBin;
use lib "$FindBin::Bin/lib";

# Mojolicious::Liteの利用
use Mojolicious::Lite;

use utf8;

# DBD::SQLiteのバージョン
use DBD::SQLite;
my $sqlite_unicode
  = $DBD::SQLite::VERSION > 1.26
  ? 'sqlite_unicode'
  : 'unicode';

# データベースのためのモジュール
use DBI;

# データベースへの接続
my $database = app->home->rel_file('app.db');
my $dbh = DBI->connect(
  "dbi:SQLite:dbname=$database",
  undef,
  undef,
  {RaiseError => 1, PrintError => 0, AutoCommit => 1,
  $sqlite_unicode => 1}
);

# テーブルの作成
$dbh->do(<<"EOS");
create table if not exists entry(
  id INTEGER PRIMARY KEY,
  message
);
EOS

# トップページ
get '/' => sub {
  my $self = shift;

  my $sth = $dbh->prepare(<<"EOS");
select message from entry order by id desc;
EOS

  $sth->execute;

  my $rows = [];
  while (my $row = $sth->fetchrow_hashref) {
    push @$rows, $row;
  }

  $self->render(rows => $rows);
} => 'index';

# データの登録
post '/register' => sub {
  my $self = shift;

  my $param = $self->req->params->to_hash;
  my $message = $param->{message} || '';

  if ($message) {
    my $sth = $dbh->prepare(<<"EOS");
insert into entry (message) values (?);
EOS
 
    $sth->execute($message);
  }
    
  $self->redirect_to('/');
};

# アプリケーションの開始
app->start;

__DATA__

@@ index.html.ep
<html>
  <head>
    <meta http-equiv="Content-type" content="text/html; charset=UTF-8">
    <%= stylesheet '/css/common.css' %>
    <title>ひとことだけメッセージ掲示板</title>
  </head>
  
  <h1>ひとことだけメッセージ掲示板</h1>
  <body>
    <form method="post" action="<%= url_for '/register' %>" >
      <div>メッセージ <input type="text" name="message"></div>
      <div><input type="submit" value="送信" ></div>
    </form>
    <div>
      % foreach my $row (@$rows) {
        <div><%= $row->{message} %></div>
        <hr>
      % }
    </div>
  </body>
</html>

(参考)FindBin

while文を使って、データベースのテーブルから一行づつ取り出しています。

パフォーマンスの問題

ローカル環境で試験をするときは、組み込みのWebサーバーがCSSなどの静的ファイルをディスパッチしてくれるので、パフォーマンスの問題は起こりません。一方さくらのレンタルサーバーではCGIというプロトコルを利用してWebアプリケーションを起動しています。CGIというプロトコルはひとつのアクセスに対してひとつのプロセスを立ち上げます。プロセスの起動という処理はとても時間がかかるので、静的ファイルをCGIでディスパッチするとパフォーマンスの劣化が顕著に見られることになります。

この問題を解決することができるでしょうか。できます。mod_rewriteというApacheのモジュールを利用して、静的ファイルがCGIとして起動されようとするときに、代わりにApacheにディスパッチさせるようにします。

これを行うためには、.htaccessというファイルを利用します。まずWindows上で

htaccess.txt

というファイルを準備してください。次にmod_rewriteのルールを記述します。

RewriteEngine on
RewriteRule ^(.*)/([^/]+).cgi/(.*)\.([0-9a-zA-Z]+)$ $1/public/$3.$4 [L]

これは.cssや.jsなどの拡張子を持ったファイルを静的ファイルとみなし、public以下の静的ファイルをApacheにディスパッチさせる設定です。

このファイルをさくらのレンタルサーバのwww以下に

.htaccess

というファイル名に変更して配置してください。これで静的ファイルを利用した場合に顕著にパフォーマンスが落ち込むことを回避できました。

CSSが適用され見出しが赤くなっているのが確認できます。現代的なWebフレームワークがとても簡単にさくらのレンタルサーバライトプランで動かせるPerlはとても良い言語です。

関連情報