Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
楽譜フォント(SMuFL)をCloudflareで配信する
Search
Ossamoon
September 11, 2025
Programming
0
96
楽譜フォント(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
390
Other Decks in Programming
See All in Programming
チームをチームにするEM
hitode909
0
380
Jetpack XR SDKから紐解くAndroid XR開発と技術選定のヒント / about-androidxr-and-jetpack-xr-sdk
drumath2237
1
190
Basic Architectures
denyspoltorak
0
120
Graviton と Nitro と私
maroon1st
0
140
AIコーディングエージェント(Manus)
kondai24
0
210
AtCoder Conference 2025
shindannin
0
530
Developing static sites with Ruby
okuramasafumi
0
330
AtCoder Conference 2025「LLM時代のAHC」
imjk
2
590
フルサイクルエンジニアリングをAI Agentで全自動化したい 〜構想と現在地〜
kamina_zzz
0
290
生成AI時代を勝ち抜くエンジニア組織マネジメント
coconala_engineer
0
9.2k
実はマルチモーダルだった。ブラウザの組み込みAI🧠でWebの未来を感じてみよう #jsfes #gemini
n0bisuke2
3
1.3k
Flutter On-device AI로 완성하는 오프라인 앱, 박제창 @DevFest INCHEON 2025
itsmedreamwalker
1
150
Featured
See All Featured
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
94
Crafting Experiences
bethany
0
22
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
100
Highjacked: Video Game Concept Design
rkendrick25
PRO
0
250
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
0
400
Code Review Best Practice
trishagee
74
19k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
31
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
1
1.3k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
28
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
290
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
190
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
0
22
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 を挟めるのでサブセットごとに細かくキャッシュ時間等を指定できる デプロイしやすさ マイナーなフォントでもためらいなくデプロイできる
終わり ご清聴ありがとうございました