Webフォントにはdeferをつけようね
FONTPLUSのサーバーが激重に
昨日の夕方に、WebフォントサービスFONTPLUSのサーバーが、アクセス集中によりハチャメチャに重くなっていたようです。それにより、このブログもページが表示されるまでかなり時間がかかるという状態になっていました。その時間帯にアクセスされていた方がいらっしゃったら申し訳ありません。状況に気づいた段階で後述の対応をとったので、今後もしまたFONTPLUSのサーバーが重くなっても、このブログはすんなりと表示されるはずです。
なぜFONTPLUSのサーバーが重くなっただけで、このブログまで重くなるのでしょうか。FONTPLUSに限らず、和文Webフォントサービスのほとんどすべてに共通することなのですが、javascriptが関係しています。和文書体は漢字というもののおかげで、一つのフォントファイルに1万文字以上のグリフデータを含まざるを得ません。データ量にして実に10MB以上です[1]Windows 10標準の游明朝で12.5MB。。自分のPCにインストールする分にはその程度のデータ量で特に問題になることはないのですが、Webフォントとして使う場合には厄介きわまりません。というのも、Webページ1つに含まれる文字の種類なんてたかが知れていて、ひらがな・カタカナと常用漢字をすべて使ったとしても2300文字程度です。常用漢字をすべて使った文章なんてまずあり得ませんから、普通は数百、多くても1000文字程度が、1ページに使う文字の種類としては限界なわけです。その1000文字程度のために、わざわざ1万文字以上のデータを全部載せしたフォントをダウンロードするのはいかにも効率が悪い。なにせ10MBです。ページ1つ表示させるのに10MBもダウンロードが必要とあっては、誰もWebフォントなんか使いませんよね。
なので、和文Webフォントの場合は普通「サブセット化」という処理を行います。あらかじめ必要になる文字種を洗い出して、その文字データだけを含んだフォントファイルを生成し、それをダウンロードさせるという処理です。そうすれば、ダウンロードするフォントはたかだか数百KBで済みますね。このサブセット化を行うにあたって、javascriptが使われるわけです。
サブセット化の具体的な流れを見ていきましょう。ここではFONTPLUSでの処理を例として説明しますが、他のWebフォントサービスでも、和文書体を扱っているのであれば大差ないはずです。まず、Webフォントを使いたいページに、 script
タグを埋め込みます。といっても必要な文字種を洗い出す処理を直接そこに書くわけではありません。文字種を洗い出す処理もかなりの行数になりますから、各ページにそんなのを貼り付けていたら非効率ですので、その処理は別途jsファイルに書いておき、Webフォントサービスのサーバーに置いておくんです。各ページの script
タグは、そのjsファイルを読み込みに行く、というだけのもの。
ページを開いてからWebフォントが表示されるまでの大まかなフローとしては、まずWebブラウザがページ中の script タグを読み取って、Webフォントサービスのサーバーにjsファイルを読み込みに行きます。そして、そのjsファイルに書かれた文字種の洗い出し処理を実行する。洗い出しができたら、ブラウザはその結果をWebフォントサービスのサーバーに伝えます。ここまでがブラウザ側の処理。ブラウザから洗い出し結果を受け取ったサーバーは、洗い出し結果に基づいてサブセットフォントを生成し、ブラウザに渡します。ブラウザはそのフォントデータを受け取ると、残りのHTMLを読み込んでページを表示させる。これで晴れてWebフォント付きのページが表示できるわけですね。
さて、ではここでWebフォントサービスのサーバーが激重になった場合、どうなるのか。実はブラウザって、特に指定しない限り並列処理はしないんですよ。どういうことかというと、言葉で解説するよりもこのページの図を見る方が分かりやすいんじゃないかなと思いますが、要はどこかの処理で詰まってしまっても、その時間に別の処理を行うことはできないんです。先ほどの説明で行くと、Webフォントサービスのサーバーにアクセスできない限り、その後の処理(HTMLの読み込み、ページの表示など)もされないままなんですね。
解決策
フォントサーバーが瀕死の時にもページをすぐに表示させるにはどうすれば良いのか。一番簡単なのは、Webフォントサービスのjsを取りに行く script
タグに defer
属性を加える、というものです。例えば、以下のような script
タグがあったとして、
<script type="text/javascript" src="//xxx">
このようにする。
<script type="text/javascript" src="//xxx" defer>
楽ちんですね。defer
は「jsファイルをダウンロードしている間もHTMLのパースを行い、パース完了後に順にjsを実行する」という命令です。
少なくともFONTPLUSとTypeSquareではこの処理をしないと、フォントサーバーが瀕死の時にページが表示されずじまいになってしまいます。Adobe Fontsは上記の対応をとらなくても大丈夫です[2]Adobe Fontsの場合、scriptタグのsrcに直接jsのありかを記述するのではなく、asyncでjsを取りに行くコードを直に記述しているため。。そんな感じ。Webフォントを使っている人は気をつけてね。
脚注