Google Fontsの日本語フォントの高速化施策が面白かった

この記事は【ウェブフォント Advent Calendar 2018】2日目参加記事です。

どうも、郁永です。

この記事は【ウェブフォント Advent Calendar 2018】2日目参加記事です。

Web大好き人間、そして、フォント大好き人間の端くれとして参加させていただきました。よろしくお願いします。

いつにも増して前置きが長いです。「一刻も早くGoogle Fontsの日本語フォントが速い理由を知りたいんじゃ!!」という方はこちらを押すと本題にジャンプできて便利です。

今年8月、Google Fontsが日本語フォントが正式リリース!

さて、今年のWebフォント界の大きなニュースといえば、「Google Fonts」で日本語フォントが正式リリースされたことではないでしょうか。

これまでGoogle Fontsの日本語フォントはEarly Access(早期アクセス、いわゆるベータ版ですね)として2年くらい前からひっそりと配信されていましたが、ついに正式リリース!

これにより、日本語圏のWebフォントの導入ハードルがググっと下がったように思います。(フォントベンダーにはしっかり対価を支払うべきだと思いますが、無料で無制限に使えるというのはやっぱり嬉しいですね!)

日本語フォントは(欧文に比べて)導入ハードルが高い、という話

Webフォントは、文字通りWebページで使うフォントのことですが、日本語フォントは(欧文フォントと比べて)導入ハードルが高いんですよね。

なぜなら? 日本語の文字の種類がとんでもなく多い=ファイルサイズが大きいからです!

欧文フォントの場合、アルファベットの大文字と小文字、数字、記号、á などのダイアクリティカルマーク付きの文字を加えても数百程度です。

しかし、日本語はひらがなとカタカナだけで100を余裕で超えます。(※五十音表を思い浮かべると90くらいのように感じますが、濁点・半濁点・拗音は別の文字として扱うため、実際は170前後あります。)

そして、漢字は小学校で習う漢字だけで1000文字以上、常用漢字まで範囲を広げるとさらに1000文字程度あります。

そうなってくると、フォントサイズ自体がどうしても欧文ファイルより大きくなってしまいます。

ちなみに、日本語と同じように膨大な量の文字を扱う言語がもう2つあります。それは中国語と韓国語で、これら3つの頭文字を取ってCJKとも言われています。

フォントサイズが大きくなってしまうと、Webフォントとして読み込んだ時に「なかなか文字が表示されない」といったことが起こります。

Webフォントを配信しているサービスもそういった事態は把握していて、サブセット化などの対策をしています。

サブセット化とは:
フォントの中に含まれている文字の中から、必要なものだけを抜き出してファイルサイズを小さくすることです。例えば、JavaScriptなどでページ内で使われている文字のフォントだけを後出しで読み込ませるなどがこれにあたります。

では、Google Fontsで配信している日本語フォントは、どんな高速化の対策をしているのでしょうか?

Google Fontsの日本語フォントの読み込み高速化施策

GoogleとAdobeが開発した「Noto Sans JP」を例に見てみましょう。

「Noto Sans JP」を読み込むタグはこちらです。

<link href="https://fonts.googleapis.com/css?family=Noto+Sans+JP" rel="stylesheet"&&gt;

純粋にCSSを読み込んでいますね。それでは中身を見てみましょう!

こちらです! ばばん!

/* [0] */
@font-face {
  font-family: 'Noto Sans JP';
  font-style: normal;
  font-weight: 400;
  src: local('Noto Sans Japanese Regular'), local('NotoSansJapanese-Regular'), url(https://fonts.gstatic.com/s/notosansjp/v18/-F62fjtqLzI2JPCgQBnw7HFow2os2HUP5pp0erwTqsSGs8dLiZ-nVOFVLsE_RS1PblwsiBhLorUfH78.0.woff2) format('woff2');
  unicode-range: U+28946, U+28949, /*...(中略)...*/ U+2f9de-2f9df, U+2f9f4;
}
/* [1] */
@font-face {
  font-family: 'Noto Sans JP';
  font-style: normal;
  font-weight: 400;
  src: local('Noto Sans Japanese Regular'), local('NotoSansJapanese-Regular'), url(https://fonts.gstatic.com/s/notosansjp/v18/-F62fjtqLzI2JPCgQBnw7HFow2os2HUP5pp0erwTqsSGs8dLiZ-nVOFVLsE_RS1PblwsiBhLorUfH78.1.woff2) format('woff2');
  unicode-range: U+243bc, U+243d0, /*...(中略)...*/ U+286d7, U+286fa;
}
/*...(中略)...*/
/* [119] */
@font-face {
  font-family: 'Noto Sans JP';
  font-style: normal;
  font-weight: 400;
  src: local('Noto Sans Japanese Regular'), local('NotoSansJapanese-Regular'), url(https://fonts.gstatic.com/s/notosansjp/v18/-F62fjtqLzI2JPCgQBnw7HFow2os2HUP5pp0erwTqsSGs8dLiZ-nVOFVLsE_RS1PblwsiBhLorUfH78.119.woff2) format('woff2');
  unicode-range: U+20, U+3001-3002, /*...(中略)...*/ U+ff0c, U+ff0e;
}

……むむっ?!

フォントの指定している @font-face が120個も並んでいます。

しかも全部、font-weight:400の「Noto Sans JP」です。

どういうことなの…?

これはバグでも誤発注でもありません!

よく見ると、各 @font-face で「unicode-range」が指定されていますね?

これは、Unicodeコードポイントの範囲を表していて、

  • 指定したコードポイントの文字だけそのフォントで表示する
  • Webページ内に該当する文字があるときだけsrcのフォントを読み込む

という性質があります。

つまり「膨大なフォントファイルでも、120個に分割してページの表示に必要なものだけ読み込めば、読み込むファイルサイズを削減できる」というワケです!

また、 local(‘Noto Sans Japanese Regular’) で「既に同名のフォントがローカル上にあればそれを読み込んで」いるので、余計なフォントファイルを読み込まないようになっています。

Google Fontsはファイルサイズの小さい「woff2」形式のWebフォントを配信していますが、これはIE11などのレガシーブラウザでは非対応の形式です。

Google Fontsでは、そのような非対応環境でCSSを呼び出された時は「woff」形式のフォントを返すようにしています。

余談

ちなみに、ただ機械的に120個に分割したわけないじゃないみたいですよ!

日本語フォントが配信された際のプレスリリースにはこんなことが書かれていました。

Google Design
Google Fonts launches Japanese support—and makes loading large fonts even faster

記事の前半では、日本語フォントが(文字の種類が多いため)ファイルサイズが大きなってしまう問題点に触れています。

そして注目すべきはこちらの一文。

Google Fonts’ innovative delivery system circumvents this problem by splitting the large fonts into roughly 100 “slices” based on an analysis of online language patterns.

日本語訳するとこんな感じです。

Google Fontsの革新的な配信システムでは、オンライン言語パターンの分析に基づきフォントをおよそ100の「スライス」に分割することにより、この問題を回避します。

なんと、言語パターンの分析してフォントを分割したそうです。

どのように分割しているのかチョット気になりますが……それはまた次の機会で。

それではまた。

コメント