blog-java1では、JavascriptとCSSの結合と最小化を行っています。独自の仕組み「asset minify on-demand」を作ったので、簡単に紹介します。
ディレクトリ構造は以下のような感じです。
assets/blog.min.jsディレクトリのファイルが結合・最小化されて、main/webapp/static/blog.min.jsになります。
blog.min.js.versionは、バージョン番号が書かれたテキストファイルです。
まず、blog.jspのEL functionが解釈されます。
<script src="${as:url('/static/blog.min.js')}"></script>
EL functionは、blog.min.js.versionを読み取ります。
File verFile = new File(AppConfig.getWebappDir(), path + ".version");
if (verFile.exists()) {
String versionStr = FileUtils.readFileToString(verFile);
version = NumberUtils.toInt(StringUtils.trim(versionStr));
}
続いて、開発環境である場合は、生成対象であるblog.min.jsと
assets/blog.min.jsディレクトリ内のファイルと更新時刻を比較します。
long prevmod = destFile.lastModified();
Collection<File> files = FileUtils.listFiles(srcDir, null, false);
for (File file : files) {
if (file.lastModified() > prevmod) {
modified = true;
break;
}
}
更新されている場合は、assets/_minify.shを実行し、結合と最小化を行います。
function minify() {
name=$1
ext=${name##*.}
pushd $SRC_DIR/$name > /dev/null
cat *"$ext" > __tmp1
if [ $? != 0 ]; then
exit 1
fi
java -jar "$YUI_JAR" --charset utf-8 --type $ext __tmp1 -o __tmp2
if [ $? != 0 ]; then
exit 2
fi
...
成功した場合は、バージョンファイルを更新します。
if (exitValue == 0) {
File verFile = new File(AppConfig.getWebappDir(), path + ".version");
version = version == null ? 0 : version + 1;
versionMap.put(path, version);
FileUtils.write(verFile, version.toString());
}
EL functionは、バージョン番号を加えたURLを返します。HTMLへの出力は以下のようになります。
<script src="/blog/static/blog.min.js;v=17"></script>
バージョン番号をクエリ文字列 "?v=17"とせず、パラメータ ";v=17"としているのは、プロキシサーバ(特にsquid)でキャッシュを有効にするためです。
まあいい感じです。
似たようなことはGruntでもできるようなので、機会があれば調査したいです。