Webフォントをできるだけ軽く表示する圧縮の.htaccessや遅延ロードJSを作ってみた
今日は、Webフォントのお話しを。Web担で初めてWebフォントを使ってみたのですが、予想どおり転送量が大きくてページ表示が重くなるので、できるだけ表示が快適になるように工夫してみました。
脱・新人Web担!あずさのWeb担当者日記という新コーナーで、Webフォントを使いました。
イベントなどでも女性Web担当者の数が増えていることから、現場の女性の方に執筆を依頼し、担当編集者も女性にして、女性向けの記事として作ってもらったら、「女性誌っぽいデザインにしたい」ということで、Webフォントを使うことになったのです。
しかし、重い! どれぐらい重いかというと、HTMLやCSSやJSや画像を全部あわせても740Kバイトぐらいなのに、フォントファイル1つで3.2Mバイトもあるのです!
Webフォントを使ってもできるだけページ表示を軽くするための注意点や工夫点をお伝えします。
ポイント1:本当に効果的なところ以外では使わない
なので、第1のポイントは「本当に効果的なところ以外では使わない」こと。
最初はタイトルや見出しなどにもWebフォントを使っていたのですが、デフォルトの表示と大きく変わるわけではないので、そこはWebフォントの適用を中止しました。
ポイント2:Webフォントは圧縮する
今回利用したWebフォントは、3.2Mバイトのサイズがあります。そのまま転送すると600ミリ秒~1秒の時間がかかります(他の環境やモバイルなどではもっとかかります)。
Webサーバー側で圧縮した状態で送り出すことで、転送サイズを減らしましょう。そのためには、.htaccessなどで次のような指示をします(Webサーバーでmod_deflateが有効になっている必要あり)。
<IfModule mod_mime.c>
AddType font/opentype .otf
AddType font/eot .eot
AddType font/truetype .ttf
AddType application/font-woff .woff
</IfModule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE font/opentype font/eot font/truetype application/font-woff
</IfModule>
これで、Webフォントへのアクセスは自動的にWebサーバーが圧縮して転送してくれ、転送量が2.3Mバイト、転送時間は450ミリ秒~800ミリ秒になりました。
さらに、毎回の圧縮処理が入るとアクセスが多いときには負荷になるだろうと、あらかじめgzip圧縮したフォントファイルをサーバー上の同じ場所に作っておいて、圧縮ファイルがある場合はそちらを転送するようにしました。
<IfModule mod_rewrite.c>
RewriteCond %{HTTP:Accept-encoding} !gzip
RewriteRule .* - [S=4]
RewriteCond %{REQUEST_URI} \.otf$
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}\.gz -s
RewriteRule .* %{REQUEST_URI}\.gz [L,QSA,T=font/opentype,E=no-gzip:1]
RewriteCond %{REQUEST_URI} \.eot$
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}\.gz -s
RewriteRule .* %{REQUEST_URI}\.gz [L,QSA,T=font/eot,E=no-gzip:1]
RewriteCond %{REQUEST_URI} \.ttf$
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}\.gz -s
RewriteRule .* %{REQUEST_URI}\.gz [L,QSA,T=font/truetype,E=no-gzip:1]
RewriteCond %{REQUEST_URI} \.woff$
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}\.gz -s
RewriteRule .* %{REQUEST_URI}\.gz [L,QSA,T=application/font-woff,E=no-gzip:1]
</IfModule>
Webフォントは正しいコンテントタイプをHTTPヘッダーで返さないとブラウザがWebフォントとして扱ってくれない場合があります。最初、そこにハマりました。
RewriteRuleのT
フラグでコンテントタイプを指示できると思ったのですが、うまくいかなかったので、結局次のようにしてForceType
ディレクティブで強引に上書きしています。このあたりはもう少し調べてみます。
<FilesMatch "\.(?i:otf(\.gz)?)$">
ForceType font/opentype
</FilesMatch>
<FilesMatch "\.(?i:ttf(\.gz)?)$">
ForceType font/eot
</FilesMatch>
<FilesMatch "\.(?i:eot(\.gz)?)$">
ForceType font/truetype
</FilesMatch>
<FilesMatch "\.(?i:woff(\.gz)?)$">
ForceType application/font-woff
</FilesMatch>
ちなみに、最初にテストしたときはWebサーバーによる圧縮に時間がかかっているように見えたのですが、いまチェックしてみると、mod_deflateで圧縮した場合と比べて、特にリクエストに対する反応時間は変わっていませんでした。ですから、わざわざ圧縮済みファイルを置いておく効果はほとんどないかもしれません(アクセスが多い時間帯だと変わるのかな)。
まぁ、gzipで圧縮する際に最高圧縮率に設定したので4Kバイトほと節約できているのがメリットでしょうか。
手法 | 転送サイズ | 転送時間の例 |
---|---|---|
非圧縮 | 3.2MB(3,311,516バイト) | 600ms~1000ms |
Apacheのmode_deflate圧縮(標準) | 2.3MB(2,415,239バイト) | 450ms~800ms |
gzip事前圧縮 | 2.3MB(2,411,075バイト) | 400ms~800ms |
ポイント3:ブラウザ側でキャッシュできるようにする
重いWebフォントファイルを何度もWebサーバーから取得する必要はありません。一度表示したWebフォントは、ブラウザがキャッシュして二度とサーバーに読みに行かないようにしましょう。
<FilesMatch "\.(?i:(otf|ttf|eot|woff)(\.gz)?)$">
ExpiresDefault A25920000
</FilesMatch>
これで、一度Webフォントファイルにアクセスした時点から300日間は、同じURLのフォントファイルを参照する場合でもサーバーに読みに行かずにローカルのキャッシュを使ってくれます。
ポイント4:Webフォントの適用を遅らせる
それでもやはりフォントの処理で1秒ぐらい余分にかかるのでWebフォントの適用をページ表示から少し遅らせることにしました。
まず、@font-faceの定義を独立したCSSファイルに移動してそのファイルはページから直接には読み込まないようにすることで、ページを表示しただけではフォント定義が読み込まれないようにします(つまりフォントファイルにもアクセアスしない)。
その状態で、グーグルのWbFont Loaderを使って、ページ表示が完了してから遅らせてフォントを適用します。
<script type="text/javascript">
WebFontConfig = {
custom: {
families: ['HuiFont'],
urls: ['/files/css/fonts.css'] // @font-face指定CSSファイル
}
};
$(document).ready(function() {
setTimeout(
function() {
var wf = document.createElement('script');
wf.src = ('https:' == document.location.protocol ? 'https' : 'http') + '://ajax.googleapis.com/ajax/libs/webfont/1.4.7/webfont.js';
wf.type = 'text/javascript';
wf.async = 'true';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(wf, s);
},
5000
);
});
</script>
この例では、ブラウザがページ表示を構築してから5秒後にWebフォントを適用しています。
ポイント5:ローカルの校正HTMLファイルでは適用できない
Webフォントは原則として「同じドメイン名じゃないと使えない」ものです。
どういうことかというと、Web担のサーバーに置いてあるWebフォントファイルは、Web担のサーバー上のHTMLファイルからでないと使えないのです。
ふだんはそれで問題ないのですが、校正用HTMLをHTMLファイルで関係者に送って確認してもらう場合には、その校正HTMLファイルをローカルにダウンロードして開いてもWebフォントが反映されません。
同じサーバーにあるHTML以外からもWebフォントを使えるようにするには、HTTPヘッダーでそれを指示しなければいけません。具体的には、.htaccessなどで次の命令を記述します。
<FilesMatch "\.(?i:(otf|ttf|eot|woff)(\.gz)?)$">
Header set Access-Control-Allow-Origin *
</FilesMatch>
外部サーバーが決まっている場合はそのサーバー名を記述すればいいのですが、前述のようなローカルにダウンロードしたHTMLファイルの場合は、さまざまなブラウザで使えるようにするには上記の記述が必要になります。
ただし、こうすると、だれでもそのWebフォントを使えるようになってしまう点に注意が必要です。Web担では上記の指示は入れていません。
ソーシャルもやってます!