SVGファイルをサーバ側で圧縮する

SVGファイルの実態はシンプルなXMLなので、HTMLやCSSと同じようにサーバ側での圧縮が可能です。方法としては以下の3つが考えられるでしょう。

  1. mod_deflate を使って圧縮する方法
  2. 事前に圧縮し、SVGZファイルとして配信する方法
  3. 2の方法にgzip非対応ブラウザ用のフォールバックを追加した方法

以下の動作確認は全て Apache 2.4.34 で行なっています。

mod_deflate を使って圧縮する方法

mod_deflate は HTTPリクエストの Accept-Encoding ヘッダーをもとに、ブラウザが gzip に対応している場合のみ圧縮を行います。

gzip に対応していないブラウザでも(圧縮はされないものの)、画像が表示されなくなるといったことはありません。しかし、リクエストのたびに圧縮を行うため、サーバの負担が大きくなるというデメリットがあります。

設定方法

まず、mod_deflate が有効になっていない場合は httpd.conf を修正して有効化する必要があります。

LoadModule deflate_module modules/mod_deflate.so

次に .htaccess (またはhttpd.conf)で SVGファイルが圧縮されるように AddOutputFilterByTypeディレクティブを指定します。

AddOutputFilterByType DEFLATE image/svg+xml

デモ(圧縮無し)
デモ(mod_deflate での圧縮)

SVGZファイルとして配信する方法

SVGファイルを gzip で圧縮したものを SVGZファイルと呼びます。

事前にファイルを圧縮しておくことでサーバの負担を減らすことができます。そのかわり常に gzip で圧縮したファイルを返すため、gzip に対応しないブラウザではファイルを正常に扱えず、表示できなくなります。

設定方法

まず SVGファイルを gzip コマンドで SVGZファイルに変換します。

$ gzip ebi.svg
$ mv ebi.svg.gz ebi.svgz

そして .htaccess で、SVGZファイルが gzip で圧縮されていることをクライアントに知らせるために AddEncoding ディレクティブを使用します。

AddEncoding x-gzip .svgz

デモ(SVGZ での圧縮)

SVG、SVGZ の両ファイルを用意して配信する方法

上記で紹介した方法の『gzip非対応ブラウザで表示されなくなる』というデメリットを補う方法です。あらかじめ SVGファイル、SVGZファイルの両方を用意しておき、gzip 対応ブラウザには SVGZファイルを、非対応ブラウザには SVGファイルを返します。

設定方法

SVGファイルのリクエスト時にSVGZファイルを返す処理を行うには mod_rewrite を使います。そのため、まず mod_rewrite が有効になっていない場合は httpd.conf で有効化する必要があります。

LoadModule rewrite_module modules/mod_rewrite.so

そして .htaccess で以下の設定をします。

AddEncoding x-gzip .svgz

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} \.svg$
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}z -s
RewriteRule .+ %{REQUEST_URI}z [L]

AddEncoding ディレクティブは上記の方法と同じように SVGZファイルが gzip 圧縮されていることを示しています。

次の段落のリライトルールでは、『リクエストされたファイルがSVGファイルかどうか』、『リクエストの Accept-Encoding ヘッダに gzip が含まれるか』、『対応するSVGZファイルが存在するか』を一つずつ検査し、全てに該当するリクエストの場合にのみ SVGZファイルを返すよう指定しています。

これによってサーバの負担を減らし、なおかつ gzip 非対応ブラウザでも表示できるようになります。

デモ(SVGとSVGZをリクエストによって切り替え)

おわり

.htaccess の編集や gzip コマンドでの圧縮など、手間はかかりますが、SVGファイルをサーバ側で圧縮する場合は3つめの方法が一番良いと思います。

『gzip に対応していないブラウザ』と何度か書きましたが、実際のところそんなものは今の時代使われてないでしょう。そのため2つ目の方法でも動作しないということはほぼないと思います。

重要なのはリクエストの Accept-Encoding を見て、適切なレスポンスを返すことです。ちゃんと Accept-Encoding を見ることで、仮に宗教上の理由で gzip が使えなかったり、あるいは gzip に重大な脆弱性が見つかり gzip を完全廃止する世界がやってきた場合でも、gzip を使用するかどうかの判断をユーザに委ねることができます。

どこまでクライアント側の事情に対応するかが難しいところですが、HTTP自体の仕様にAccept-Encoding がある以上はそれに準拠した動作の方が望ましいでしょう。