はじめに
JavaScriptは、転送量を抑えるために利用できる技術として、「minify」が挙げられます。
通常はタスクランナー等で処理を行ってからデプロイするわけですが、これをnginx側でやらせることによって、デプロイ工数の削減が期待できます。
公式ページのEmbedded Perl Minify JSによると、perlプラグインを利用することで、で比較的簡単に実現できそうです。
nginxのperlモジュールを有効化する
perlは、例えばaptやyumなどでインストールを行った場合、デフォルトで有効になっているとは限りません。まずこれらを有効にする必要があります。
yumの場合
CenoOS系に代表されるyumの場合、/usr/share/nginx/modules
あたりにconfファイルが存在するはずですが、ない場合はモジュールを追加します。
モジュールのインストール
$ yum install nginx-mod-http-perl
または、
$ yum install nginx-all-modules
perlモジュールの読み込み
以下のコードをnginx.conf(または準ずるファイル)のトップレベルに記述します。
include /usr/share/nginx/modules/mod-http-perl.conf
aptの場合
debian系のaptの場合は、libnginx-mod-http-perlパッケージをインストールする必要があります。
モジュールのインストール
$ sudo apt install libnginx-mod-http-perl
perlモジュールの読み込み
/etc/nginx/modules-enabledに50-mod-http-perl.confがあればOKです。
なければ、modules-availableからシンボリックリンクを貼りましょう。/etc/nginx/modules-available
か、もしくは/usr/share/nginx/modules-available/
にモジュールがあるかと思います。
いずれにもない場合は、findなどで検索するとよいでしょう。
$ sudo ln -s /usr/share/nginx/modules-available/50-mod-http-perl.conf /etc/nginx/modules-enabled
JavaScript Minifierを配置する
CPANでJavaScript::Minifierをインストールします。
> install JavaScript::Minifier
モジュール自体は、CPANからダウンロードして@INCのパスが通っているところに配置することも出来ます。
@INCのパスは、以下のコマンドで確認できます。
$ perl -e 'use Data::Dumper;print Dumper @INC'
Minify.pmを配置する
公式のperl/Minify.pmを参考にして、同じく@INCのパスが通っているところに配置します。
もしperlが書けるなら、これを編集することでより柔軟性のあるスクリプトを組むことができます。参考として、変更できそうなところをコメントしておきます。
package Minify;
use nginx;
use JavaScript::Minifier qw(minify);
sub handler {
my $r=shift;
my $cache_dir="/tmp"; # Cache directory where minified files will be kept # キャッシュディレクトリです。デフォルトは/tmpに配置するようになっています。
my $cache_file=$r->uri; # 引数オブジェクト内のuriをそのままキャッシュファイル名とします。Cache Bustingを行うならquery_stringも付加するとよいでしょう。
$cache_file=~s!/!_!g; # キャッシュファイル名に/があれば、_に置換しています。
$cache_file=join("/", $cache_dir, $cache_file);
my $uri=$r->uri;
my $filename=$r->filename;
return DECLINED unless -f $filename;
if (! -f $cache_file) {
open(INFILE, $filename) or die "Error reading file: $!";
open(OUTFILE, '>' . $cache_file ) or die "Error writting file: $!";
minify(input => *INFILE, outfile => *OUTFILE);
close(INFILE);
close(OUTFILE);
}
$r->send_http_header("application/javascript");
$r->sendfile($cache_file);
return OK;
}
1;
__END__
参考:Module ngx_http_perl_module
nginx設定を変更する
準備が完了したら、nginxの設定を変更します。
serverディレクティブ以下に下記を追記します。
location ~ \.js$ {
perl Minify::handler;
}
nginxをリロードします。
sudo systemctl reload nginx
注意点
このモジュールを使うときに注意すべき点がいくつかありますので、挙げておきます。
初回のアクセスは遅い
リクエストを受けたときに初めてMinifyが実行されます。2回目以降はキャッシュが作られるので問題ありませんが、初回導入時は気を付ける必要があります。
デプロイ後は、すべてのリソースに一度はアクセスしておくのがよいでしょう。
JavaScriptを更新したときにキャッシュの削除が必要
キャッシュがあると、必ずそちらを使うようになっています。
Minify.pmでファイルのタイムスタンプを比較するという手段もありますが、速度が犠牲になるため一長一短です。
/tmpをキャッシュディレクトリにしている場合、一定のタイミングでキャッシュが削除される
意図しないタイミングでキャッシュ削除が起こり、レスポンスが一時的に劣化する可能性があります。
保持しておきたい場合は、キャッシュディレクトリを変更しておきましょう。
my $cache_dir="/path/to/cachedir";
まとめ
この手順を適用することで、毎回Minify作業を実施することなく、自動的にMinifyが掛かってくれるようになります。
タスクランナーでMinifyを自動化してデプロイするほうが主流ですが、こういうやり方もあるということで、参考程度にしていただけると幸いです。