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

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

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

Google Fontsで日本語フォントが正式リリース!

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

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

これにより、日本語圏のWebフォントの導入ハードルがググっと下がったように思います。

前置き:日本語フォントは欧文に比べて導入ハードルが高い

Webフォントは その名の通りWebページで使えるフォントのことですが、日本語のフォントは欧文(英語)のフォントと比べて導入ハードルが高いのです。

理由は簡単。日本語の文字の種類が多く、ファイルサイズが大きくなってしまうからです!

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

しかし、日本語はひらがなとカタカナだけで100を余裕で超えます。

五十音表を思い浮かべると90くらいのように感じますが、濁点・半濁点・拗音は別の文字として扱うため、実際は170前後あります。

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

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

フォントサイズが大きくなると、Webフォントとして読み込むのに時間がかかる問題が生じます。

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

サブセット化
フォントの中に含まれている文字の中から、必要なものだけを抜き出してファイルサイズを小さくすることです。
例えばJavaScriptを用いて、ページ内で使われている文字のフォントだけを後出しで読み込ませる、などがこれにあたります。
CJK
ちなみに、日本語と同じように膨大な量の文字を扱う言語がもう2つあります。それは中国語(Chinese)韓国語(Korean)で、これら3つの頭文字をとってCJKとも言われています。

では、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">

純粋に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」です。

unicode-range でページの表示に必要なフォントファイルだけ読み込んでいた!

よく見ると、各 @font-faceunicode-range が指定されていますね。

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

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

という性質があります。

例えば「郁永」という文字をWebフォントで表示する場合、120個のフォントファイルのうち「郁」を含むフォントファイルと「永」を含むフォントファイルの2つだけを持ってくる、というワケです。

つまり膨大なフォントファイルを120個に分割して、ページの表示に必要なものだけ読み込むことで高速化を実現しているということです。

さらに、local(‘Noto Sans Japanese Regular’) があることで、端末内に同名のフォントがあればフォントを新たに読み込まないようになっています。

余談:ただ単純に120個に分割しているわけじゃない?!

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

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

参考 Google Fonts launches Japanese supportGoogle Design

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

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

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の「スライス」に分割することにより、この問題を回避します。

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

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

それではまた。