Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
楽譜フォント(SMuFL)をCloudflareで配信する
Search
Ossamoon
September 11, 2025
Programming
0
76
楽譜フォント(SMuFL)をCloudflareで配信する
Google FontsとCloudflare Fontsから学ぶ配信最適化
Ossamoon
September 11, 2025
Tweet
Share
More Decks by Ossamoon
See All by Ossamoon
SSRアプリケーションにおけるPKCE付き認可コードフロー
ossamoon
0
55
RemixとCloudflare Stack におけるFile Upload
ossamoon
1
370
Other Decks in Programming
See All in Programming
Google Opalで使える37のライブラリ
mickey_kubo
3
160
Developer Joy - The New Paradigm
hollycummins
1
380
One Enishi After Another
snoozer05
PRO
0
170
ドメイン駆動設計のエッセンス
masuda220
PRO
15
6.1k
Domain-centric? Why Hexagonal, Onion, and Clean Architecture Are Answers to the Wrong Question
olivergierke
3
990
三者三様 宣言的UI
kkagurazaka
0
280
bootcamp2025_バックエンド研修_WebAPIサーバ作成.pdf
geniee_inc
0
140
TransformerからMCPまで(現代AIを理解するための羅針盤)
mickey_kubo
7
5.7k
Blazing Fast UI Development with Compose Hot Reload (Bangladesh KUG, October 2025)
zsmb
2
400
pnpm に provenance のダウングレード を検出する PR を出してみた
ryo_manba
1
170
Go言語はstack overflowの夢を見るか?
logica0419
0
650
Server Side Kotlin Meetup vol.16: 内部動作を理解して ハイパフォーマンスなサーバサイド Kotlin アプリケーションを書こう
ternbusty
3
260
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
173
15k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1k
Building an army of robots
kneath
306
46k
Facilitating Awesome Meetings
lara
57
6.6k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.2k
How to train your dragon (web standard)
notwaldorf
97
6.3k
Embracing the Ebb and Flow
colly
88
4.9k
The Pragmatic Product Professional
lauravandoore
36
7k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
253
22k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
37
2.6k
Documentation Writing (for coders)
carmenintech
75
5.1k
Transcript
楽譜フォント(SMuFL) を Cloudflare で配信する 〜Google Fonts とCloudflare Fonts から学ぶ配信最適化〜 2025/09/10
Cloudflare Workers Tech Talks in Tokyo #6 齋藤 修 (Ossamoon)
目的 楽譜もサクサクWeb に配信したい!!しかし、ニッチな分野すぎてエコシステムが成熟していない… 楽譜用のフォントを自前で効率的に配信したい! Google Fonts やCloudflare Fonts のいいところを学んで取り入れたい
目次 1. Google Fonts の配信最適化 2. Cloudflare Fonts の配信最適化 3.
楽譜フォントの標準規格SMuFL の特徴 4. SMuFL のフォントをCloudflare で配信する
目次 1. Google Fonts の配信最適化 2. Cloudflare Fonts の配信最適化 3.
楽譜フォントの標準規格SMuFL の特徴 4. SMuFL のフォントをCloudflare で配信する
Google Fonts の配信最適化 1. <link rel="preconnect"> による事前接続の確立 2. CSS の動的取得によるフォントファイル形式の選択
3. unicode-range によるサブセットの配信 4. text= パラメータによる動的サブセットの配信
None
<link rel="preconnect"> による事前接続の確立 HTML に埋め込む <link> では、CSS を取得させる他に、 preconnect を指定してGoogle
Fonts 関連ドメイ ンのDNS 解決とTLS ハンドシェイクを事前に行う <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:
[email protected]
&display=swap" rel="stylesheet" />
CSS の動的取得によるフォントファイル形式の選択 fonts.googleapis.com からCSS ファイルを動的に取得する ブラウザごとに対応する最新のフォントファイルを選択する モダンなブラウザであればwoff2 が選ばれる @font-face {
font-family: 'Noto Sans JP'; font-style: normal; font-weight: 400; font-display: swap; src: url(https://fonts.gstatic.com/s/notosansjp/~~中略~~.woff2) format('woff2'); unicode-range: U+25ee8, U+25f23, ~~中略~~, U+2f9f4; } ~~以下略~~
unicode-range によるサブセットの配信 モダンなブラウザではWeb ページ内で使用される文字を自動で認識し、必要なサブセットを自動で取得す る Noto Sans JP の場合… 一つのweight
(文字の太さ)あたり、120 のサブセットに分割 一つのサブセットあたり、対応UniCode 範囲は50~230 個程度で、woff2 ファイルサイズは10~90KB 程度
text パラメータによる動的サブセットの配信 (1/2) CSS 取得時にクエリパラメータ text を指定することで、そのテキストの文字のみを含むサブセットを生成 してくれる 例: https://fonts.googleapis.com/css?family=Noto+Sans&text=Hello
ロゴやキャッチコピーなど、意匠が必要な特定の文字列を繰り返し表示する場合に有効 フォントファイルのサイズを目一杯小さくできる 生成されたサブセットはキャッシュされ、2 回目以降はより高速に配信される
text パラメータによる動的サブセットの配信 (2/2) CSS 生成時に以下の情報がクエリパラメータに格納される kit: 与えられた text に基づくハッシュのような文字列、おそらくキャッシュのkey に利用される
skey: 謎のセキュリティキー v: フォントのバージョン unicode-range は含まず、単一のサブセットで完結 @font-face { font-family: "Noto Sans JP"; font-style: normal; font-weight: 900; font-display: swap; src: url(https://fonts.gstatic.com/l/font?kit=~~中略~~&skey=72472b0eb8793570&v=v55) format("woff2"); }
fonts.gstatic.com fonts.googleapis.com Web サーバー ブラウザ fonts.gstatic.com fonts.googleapis.com Web サーバー ブラウザ
par [preconnect] [preconnect crossorigin] HTML 取得 DNS 解決、TLS ハンドシェイク DNS 解決、TLS ハンドシェイク @font-face CSS 取得 フォントファイル取得
Google Fonts の配信最適化から学べること 1. <link rel="preconnect"> による事前接続の確立 👉 DNS 接続やTLS ハンドシェイクも最適化対象 2.
CSS の動的取得によるフォントファイル形式の選択 👉 モダンブラウザ相手ならWoff2 形式 3. unicode-range によるサブセットの配信 👉 サブセットに分割することで無駄を省くことができる 4. text= パラメータによる動的サブセットの配信 👉 究極の最適化は専用のサブセットを作ること
目次 1. Google Fonts の配信最適化 2. Cloudflare Fonts の配信最適化 3.
楽譜フォントの標準規格SMuFL の特徴 4. SMuFL のフォントをCloudflare で配信する
Cloudflare Fonts の配信最適化 1. HTML 取得時に @font-face のCSS を埋め込み 2.
フォントファイルのURL を書き換えてDNS 解決・TLS ハンドシェイクを省略 注: 現在はbeta 版、かつGoogle Fonts のみ対応
fonts.gstatic.com fonts.googleapis.com Cloudflare ブラウザ fonts.gstatic.com fonts.googleapis.com Cloudflare ブラウザ HTML 取得リクエスト
@font-face CSS 取得 HTML (@font-face CSS 埋め込み) フォント取得リクエスト フォントファイル取得 フォントファイル
Cloudflare Fonts の配信最適化から学べること 1. HTML 取得時に @font-face のCSS を埋め込み 👉 CSS は埋め込んじゃった方が速い
2. フォントファイルのURL を書き換えてDNS 解決・TLS ハンドシェイクを省略 👉 フォントファイルも独自 ドメインから配信した方が速い
目次 1. Google Fonts の配信最適化 2. Cloudflare Fonts の配信最適化 3.
楽譜フォントの標準規格SMuFL の特徴 4. SMuFL のフォントをCloudflare で配信する
楽譜フォントの標準規格SMuFL の特徴 1. 楽譜の記号がUnicode のPrivate Use Area に定義されている 2. 記号の種類ごとに細かくUnicode
の範囲が割り振られている 3. 描画に必要なのはごく一部であることが多い Standard Music Font Layout 、W3C によって策定されている標準規格
楽譜の記号がUnicode のPrivate Use Area に定義され ている Private Use Area (PUA)
は以下の範囲で定義されている独自使用が可能な領域 U+E000 ~U+F8FF: 最も一般的に利用されており、SMuFL もこの領域を利用している U+F0000 ~U+FFFFF U+100000 ~U+10FFFD 理論上はブラウザがフォントとしてレンダリングできるため、一般的なフォントの配信最適化を適用するこ とができる
None
記号の種類ごとに細かくUnicode の範囲が割り振られ ている 楽譜記号が131 の分類に分けて定義されている 例: Clefs (U+E050-U+E07F), Noteheads (U+E0A0-U+E0FF)
サブセットを分割する際にはこの分類に沿って分割することができる
特殊な記号も多く含んでおり、描画に必要なのはごく 一部であることが多い 特定の作曲家しか使っていないような特殊な記号も仕様に含んでいる 例: シュトックハウゼンの臨時記号 (U+ED50-U+ED5F) 例えば、基本的な譜面を描画する場合、必要な記号は50~100 程度 SMuFL 全体では2000
を超える記号が定められているため、必要な記号のみをピックアップしサブセット化 できれば配信最適化に大きく寄与できる
SMuFL の特徴から考える配信最適化の方法 1. 楽譜の記号がUnicode のPrivate Use Area に定義されている 👉 サブセットによる配信最適化が適用でき る 2.
記号の種類ごとに細かくUnicode の範囲が割り振られている 👉 サブセット分割の目安となる 3. 描画に必要なのはごく一部であることが多い 👉 独自のサブセットを生成するとより効率的
目次 1. Google Fonts の配信最適化 2. Cloudflare Fonts の配信最適化 3.
楽譜フォントの標準規格SMuFL の特徴 4. SMuFL のフォントをCloudflare で配信する
SMuFL のフォントをCloudflare で配信する 1. フォントの配信方法 2. 楽譜の描画ライブラリの現状と課題 3. なぜCloudflare か
フォントの配信方法 (1/2) アプリに必要なフォントだけを事前に単一のサブセットとして配信する これができるならこれがいい 事前に必要なフォントが分かっている必要がある unicode-range で分割した複数のサブセットを配信する 描画され得るフォントが、実際に描画されるフォントよりも大きくなりがちなアプリケーションに適用 できる 仕様に基づいて分類しても良いが、Google
Fonts に比べるとサブセットあたりのサイズが小さくなりが ち
フォントの配信方法 (2/2) text パラメータによる動的サブセットの生成 実装難易度が高い DoS 攻撃への対策が必須となる
R2 Cloudflare Workers ブラウザ R2 Cloudflare Workers ブラウザ HTML 取得
(@font-face CSS 埋め込み) フォント取得リクエスト フォントファイル取得 フォントファイル
デモ vexflow がjsdelivr を通して提供しているBravura 独自にサブセットを生成してCloudflare から配信したBravura vexflow とBravura を用いて簡単な楽譜を描画
interface Env { FONT_BUCKET: R2Bucket; } const app = new
Hono<{ Bindings: Env }>(); app.get("/", async (c) => { const object = await c.env.FONT_BUCKET.get("bravura/original-subset.woff2"); if (!object) { return c.json({ error: "Font not found" }, 404); } const headers = new Headers(); object.writeHttpMetadata(headers); headers.set("Content-Type", "font/woff2"); headers.set("Cache-Control", "public, max-age=31536000, immutable"); // キャッシュの設定 return c.body(object.body, { headers }); });
楽譜の描画ライブラリの現状と課題 JS 環境で楽譜の描画を行うライブラリは複数存在する vexflow abcjs verovivo いずれも最終的にsvg やcanvas 内にpath として描画するため、ブラウザがフォントのUnicode
を認識できな い ブラウザネイティブな描画ロジックを持つライブラリの登場が待たれる
なぜCloudflare か 安い 大量のトラフィックを捌いても安い 柔軟なキャッシュコントロール Workers を挟めるのでサブセットごとに細かくキャッシュ時間等を指定できる デプロイしやすさ マイナーなフォントでもためらいなくデプロイできる
終わり ご清聴ありがとうございました