スマホ向けのブラウザサービスは、モバイル回線で画像などのリソースを大量にやりとりするので、通信のもたつきを感じることが多いです。
ある時、さすがに読み込みが遅いと感じて、JavaScriptとCSSのリソースの容量を確認したら、11ファイルで742KBになっていました。
そこで、JavaScriptとCSSを圧縮することにしました。
wro4jで全てのファイルをminifyする。
まずは、よくminifyと呼ばれることをしました。
minifyとは、JavaScriptやCSSの動作に影響を与えない範囲で、不要なコメント文や空白文字を除去したり、変数名の文字数を減らしたりする処理です。
Javaには、wro4jと呼ばれるリソース圧縮ツールがあるので、これを使いました。
wro4j – Web Resource Optimizer for Java – wro4j – Google Project Hosting
wro4jは、Mavenプラグインとして導入し、ビルド時にリソースの圧縮をかけられるようにしました。
ro.isdc.wro4j
wro4j-maven-plugin
1.7.0
true
${project.basedir}/src/main/webapp/css/
${project.basedir}/src/main/webapp/js/
${project.basedir}/src/main/webapp/
${project.basedir}/src/main/webapp/WEB-INF/wro.xml
ro.isdc.wro.extensions.manager.standalone.GoogleStandaloneManagerFactory
compile
run
JavaScriptとCSSは、wro4jによって複数ファイルの結合とminifyをすることが可能です。どのファイルを圧縮するかの設定は、wro.xmlという設定ファイルに、たとえば次のように書きます。
/js/templates.js
/js/app.js
これだけでJavaScriptなどは、20〜30%くらいは容量を削減することができます。
さらにJettyの設定でレスポンスをgzip化する。
CSSは、minifyの効果があまり大きくありません。なぜなら、類似のスタイルをまとめる構文がないので、必然的に反復記述を減らせないためです。
そこで更に、HTTPの通信の際に、レスポンスボディを丸ごとgzipで圧縮します。
サーブレットコンテナにJettyを使っている場合の例です。
Jetty – Servlet Engine and Http Server
jsファイル、cssファイルのマッピングを org.eclipse.jetty.servlet.DefaultServlet にし、gzipパラメータをtrueにすることでgzip転送を利用できるようになります。
gzipServlet
org.eclipse.jetty.servlet.DefaultServlet
gzip
true
gzipServlet
/js/*
/css/*
意外と単純です。
事前にgzipファイルを用意しておく必要がある
このJettyのサーブレットによる、gzip転送は、HTTPのリクエストをされるごとにgzip圧縮をするわけではありません。
そのため事前に、非圧縮のファイルとgzip圧縮されたファイルを用意しておく必要があります。
$ ls ./js/
app.js main.js main.js.gz templates.js
こんな風に、main.jsと並列にmain.js.gzを配置しておくことで、gzipされたファイルをレスポンスしてくれます。
ちなみに、両方置いておく必要がある理由は単純です。gzip圧縮による通信に対応していないブラウザが存在するためです。
HTTP通信の際には、gzip圧縮による通信ができるかをリクエストヘッダに添えるので、これを見て、main.js.gzを返すのか、main.jsを返すのかを判断します。
GET / HTTP/1.1 Host: example.com ... Accept-Encoding: gzip, deflate ...
gzip圧縮されたファイルが用意されていない場合は、ヘッダに関わらず非圧縮のファイルが返されます。
結果、79%も削減できた。
minifyとgzip圧縮によって、容量を742KBから159KBに79%も削減することができました!
モバイルの低速回線だとかなりの体感の差になると思います。
コメント
[…] 今までは「wro4jでリソースをminifyし、Jettyでレスポンスをgzip化して通信する。」に書いたように、Mavenにフロントエンドの処理もさせていました。しかし、MavenはJavaのためのツールで、フ […]