UhiyamaLAB個人開発者の創作備忘録

FontToolsでNoto Sans JPのサブセットを作成して読み込み速度を上げる

2024/12/052024/12/05Web開発Tips

このブログの軽量化を進めるなかでフォントデータを軽量化する「サブセット化」をしてみた備忘録です。「サブセットフォントメーカー」による変換が上手くいかず、最終的に「FontTools」でNoto Sans JPをWoff2形式にして、サイズを50%以上削減+読み込み速度を高速化することができました。

  1. サブセット化とはなにか?
  2. サブセットフォントメーカーによるサブセット作成の失敗 ※OTF情報の欠落
  3. FontToolsによるサブセット作成
  4. まとめ

1. サブセット化とはなにか?

サブセット化というのは、フォントデータの中から使用する文字だけを抜き出し、不要なデータを削除して軽量化することです。「めちゃくちゃ難しい漢字とか、よくわからない記号とか絶対使わないだろうし、いちいち読み込むの無駄じゃね?だったらその部分を消して、読み込み時間短縮しようよ」って話です。

このサイトで使用しているのは、王道の「Noto Sans Japanese」です。

Noto Sans Japanese (Google Font)

これをダウンロードしてWOFF形式にして、そのままサイトに組み込むと、Regular(通常)、Bold(太字)データはいずれも4MBほどのサイズになってしまいます。もちろん、表示に問題はありませんが軽量化したいところです。


2. サブセットフォントメーカーによるサブセット作成 ※OTF情報の欠落

様々なサイトを参考にしつつ、「サブセットフォントメーカー」と「WOFFコンバータ」というソフトウェアを使って、NotoSansJPのttfをwoffに変換しましたが、問題が発生しました。

これはフォントデータを置き換えた前後のサイトの見た目を比べたものです。

左が変更前、右が変更後の画像です。記事タイトルのh2要素に注目してください。フォントデータを置き換えただけなのに、文字間の空間が広くなってレイアウトが崩れてしまっています。

実行環境や設定によるかもしれませんが、私の例でいえば、「サブセットフォントメーカー」が、NotoSansJPに含まれるOTF情報を削除してしまったのが原因のようです。

OTF情報とは、OpenTypeフォントが持つ重要なデータのことで、文字間調整(GPOSテーブル)、字形置換(GSUBテーブル)等で構成されています。今回の問題は、サブセットフォントメーカーの変換中にOTF情報が削除されたことで文字間スペースや字形置換が正しく機能しなくなったと考えました。

そしてOTF情報を維持したままサブセットを作成できる方法として見つけたのがFontToolsです。


3. FontToolsによるサブセット作成

FontToolsは、Pythonで開発されたオープンソースのフォント操作ライブラリです。TrueTypeフォント(TTF)やOpenTypeフォント(OTF)を操作するための様々な機能を提供し、フォントのサブセット化、フォント情報の編集等を行うことができます。

FontTools (Github)

3-1. FontToolsのインストール

FontToolsはPythonで動作するため、まずPython環境をセットアップしてください。

次にFontToolsをインストールします。

pip install fonttools

3-2. サブセット化コマンドを実行

下記のコマンドをコピペして実行します。指定するフォント名とoutputの書き出し名については各々変更してください。

pyftsubset NotoSansJP-Regular.ttf \
  --output-file=NotoSansJP-Regular.woff2 \
  --flavor=woff2 \
  --layout-features="*" \
  --unicodes="U+0020-007E,U+3000-30FF,U+4E00-9FAF" \
  --with-zopfli \
  --verbose

コマンドの解説をします。

  • NotoSansJP-Regular.ttf

    サブセット化する元のフォントファイルのパスを指定します。

  • --output-file=NotoSansJP-Regular.woff2

    出力ファイル名を指定します。この例ではWOFF2形式で保存します。

  • --flavor=woff2

    出力フォントの形式をWOFF2に指定します。WOFF2は圧縮効率が高く、Web用フォントに最適です。

  • --layout-features="*"

    OpenTypeレイアウト機能(例: カーニング、字形の代替など)を含めます。

  • --unicodes="U+0020-007E,U+3000-30FF,U+4E00-9FAF"

    含める文字のUnicode範囲を指定します。

    • U+0020-007E:基本的な英数字と記号(ASCII)
    • U+3000-30FF:全角記号、ひらがな、カタカナ
    • U+4E00-9FAF:CJK統合漢字(基本漢字)
  • --with-zopfli

    Zopfliアルゴリズムを使用してWOFF2ファイルをさらに圧縮し、サイズを最小化します。

  • --verbose

    実行中の詳細なログを表示します。エラーの追跡や確認に便利です。

これでフォントデータと同じ階層にWoff2が作成されます。あとはそれを既存のフォントデータと置き換えるだけです。例えば下記のようにCSSを変更します。

@font-face {
    font-family: 'Noto Sans JP';
    src: url('/fonts/NotoSansJP-Regular.woff2') format('woff2');      
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Noto Sans JP';
    src: url('/fonts/NotoSansJP-Bold.woff2') format('woff2');        
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

4. まとめ

今回のFontToolsによるサブセット化によりフォントデータを軽量化することができました。

ファイルサイズは半分になって、読み込み時間も改善しています。ここから様々な調整を加えて更に軽量化することも可能だと思うので、いろいろ工夫してみてください。

この記事をシェアする