Google Fontsのunicode-rangeを使ったサブセット方法 - 祝 Noto Sans / Serif JP on Google Fonts

Google FontsでNoto Sans JP / Noto Serif JPが提供されるようになったということで（以前から他の日本語フォントも提供してましたが）、試してみたら、けっこう軽かったので、どのようにサブセットをしてるかの解説です。

[Google Fontsのunicode-rangeを使ったサブセットがわかりよいデモ](http://ksk1015.github.io/google-fonts-subset-demo/)

Noto Sans JPの1ウェイトのみのcssファイルは以下のようになってます。

https://fonts.googleapis.com/css?family=Noto+Sans+JP

```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/v15/-F62fjtqLzI2JPCgQBnw7HFowwII2lcnoeA3frgQrvWXpdFgzKXkFY85dZISEzd2Lgk_okkQpbQPZNoSzU1r.0.woff2) format('woff2');
  unicode-range: U+28946, U+28949, U+2896b, U+28987-28988, U+289ba-289bb, U+28a1e, U+28a29, U+28a43, U+28a71, U+28a99, U+28acd, U+28add, U+28ae4, U+28bc1, U+28bef, U+28cdd, U+28d10, U+28d71, U+28dfb, U+28e0f, U+28e17, U+28e1f, U+28e36, U+28e89, U+28eeb, U+28ef6, U+28f32, U+28ff8, U+292a0, U+292b1, U+29490, U+295cf, U+2967f, U+296f0, U+29719, U+29750, U+29810, U+298c6, U+29a72, U+29d4b, U+29ddb, U+29e15, U+29e3d, U+29e49, U+29e8a, U+29ec4, U+29edb, U+29ee9, U+29fce, U+29fd7, U+2a01a, U+2a02f, U+2a082, U+2a0f9, U+2a190, U+2a2b2, U+2a38c, U+2a437, U+2a5f1, U+2a602, U+2a61a, U+2a6b2, U+2a9e6, U+2b746, U+2b751, U+2b753, U+2b75a, U+2b75c, U+2b765, U+2b776-2b777, U+2b77c, U+2b782, U+2b789, U+2b78b, U+2b78e, U+2b794, U+2b7ac, U+2b7af, U+2b7bd, U+2b7c9, U+2b7cf, U+2b7d2, U+2b7d8, U+2b7f0, U+2b80d, U+2b817, U+2b81a, U+2f804, U+2f80f, U+2f815, U+2f818, U+2f81a, U+2f822, U+2f828, U+2f82c, U+2f833, U+2f83f, U+2f846, U+2f852, U+2f862, U+2f86d, U+2f873, U+2f877, U+2f884, U+2f899-2f89a, U+2f8a6, U+2f8ac, U+2f8b2, U+2f8b6, U+2f8d3, U+2f8db-2f8dc, U+2f8e1, U+2f8e5, U+2f8ea, U+2f8ed, U+2f8fc, U+2f903, U+2f90b, U+2f90f, U+2f91a, U+2f920-2f921, U+2f945, U+2f947, U+2f96c, U+2f995, U+2f9d0, 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/v15/-F62fjtqLzI2JPCgQBnw7HFowwII2lcnoeA3frgQrvWXpdFgzKXkFY85dZISEzd2Lgk_okkQpbQPZNoSzU1r.1.woff2) format('woff2');
  unicode-range: U+243bc, U+243d0, U+24629, U+246a5, U+247f1, U+24896, U+248e9, U+24a4d, U+24b56, U+24b6f, U+24c16, U+24d14, U+24e04, U+24e0e, U+24e37, U+24e6a, U+24e8b, U+24ff2, U+2504a, U+25055, U+25122, U+251a9, U+251cd, U+251e5, U+2521e, U+2524c, U+2542e, U+2548e, U+254d9, U+2550e, U+255a7, U+2567f, U+25771, U+257a9, U+257b4, U+25874, U+259c4, U+259cc, U+259d4, U+25ad7, U+25ae3-25ae4, U+25af1, U+25bb2, U+25c4b, U+25c64, U+25da1, U+25e2e, U+25e56, U+25e62, U+25e65, U+25ec2, U+25ed8, U+25ee8, U+25f23, U+25f5c, U+25fd4, U+25fe0, U+25ffb, U+2600c, U+26017, U+26060, U+260ed, U+26222, U+2626a, U+26270, U+26286, U+2634c, U+26402, U+2667e, U+266b0, U+2671d, U+268dd, U+268ea, U+26951, U+2696f, U+26999, U+269dd, U+26a1e, U+26a58, U+26a8c, U+26ab7, U+26aff, U+26c29, U+26c73, U+26c9e, U+26cdd, U+26e40, U+26e65, U+26f94, U+26ff6-26ff8, U+270f4, U+2710d, U+27139, U+273da-273db, U+273fe, U+27410, U+27449, U+27614-27615, U+27631, U+27684, U+27693, U+2770e, U+27723, U+27752, U+278b2, U+27985, U+279b4, U+27a84, U+27bb3, U+27bbe, U+27bc7, U+27c3c, U+27cb8, U+27d73, U+27da0, U+27e10, U+27fb7, U+2808a, U+280bb, U+28277, U+28282, U+282f3, U+283cd, U+2840c, U+28455, U+2856b, U+285c8-285c9, 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/v15/-F62fjtqLzI2JPCgQBnw7HFowwII2lcnoeA3frgQrvWXpdFgzKXkFY85dZISEzd2Lgk_okkQpbQPZNoSzU1r.119.woff2) format('woff2');
  unicode-range: U+20, U+3001-3002, U+3041-3057, U+3059-307b, U+307d-307f, U+3081-308f, U+3091-3093, U+3099-309a, U+30a1-30e1, U+30e3-30ed, U+30ef-30f0, U+30f2-30f4, U+30fb-30fc, U+ff0c, U+ff0e;
}
```

120個のfont-faceでunicode-rangeを指定して定義して、そのunicode-rangeのサブセットのフォントファイルを指定してるようです。

unicode-rangeのことをいまいち理解してなかったんですが、unicode-rangeで指定した文字列がそのfont-familyで表示しようとしたとき、ブラウザは初めてsrcで指定してるフォントファイルを読み込もうとするようです。

Noto Sans JPで表示してるテキストが「イチゴだいふく」だけなら、ひらがなカタカナがいる[119]のfont-faceのフォントファイルのみを読み込みます。これは動的に検知するようで、jsで書き換えてもその都度検知して必要なフォントファイルがあれば読み込んでくれます。

120個の分け方も、機械的に分けたのではなく、使用頻度を考慮した分け方っぽいです。