Skip to content

Repository files navigation

Zitrange

Chinese webfont subsetting & font splitting — 中文字体分包 / 子集化工具:按 unicode-range 把 CJK 字体切成 woff2 分片并生成 @font-face,让浏览器只下载页面真正用到的字。纯本地运行, 字体文件全程不出本机。

  • 支持 .ttf .otf .woff2 .ttc .otc,输出 woff2 / woff / ttf
  • 分片模式与兜底字表可按需组合,分片产物可逐片或一次性下载
  • 内置「字体��览」「分片清单」「体积对比」「按需加载模拟」

界面预览

Zitrange 界面预览


1. 它能解决什么

一个完整的中文字体往往 5–20MB,但一个网页真正用到的字通常只有几百到几千个。 Zitrange 会:

  1. 根据你提供的「字符集」从字体里裁出需要的字形(子集化);
  2. 按频次把字符切成若干递增大小的分片(高频字进小片);
  3. 为每片生成带 unicode-range 的 @font-face,浏览器按需下载。

典型效果:原始 12MB 字体 → 实际首屏只下载几十 KB 的命中分片。

同赛道的工具还有 font-spider(字蛛)、fontmin、cn-font-split(中文网字计划)等:它们多在构建期 自动扫描源码取字;Zitrange 走的是「本地可视化 + 可调分片策略 + 产物落盘」的路子——排序可按 文本频次 / 通用字频 / 码位邻近 / 码块均分四种,配合兜底字表与 ASCII 首屏片自由组合, 且不做任何上传。


2. 环境要求

依赖 版本 用途
Node.js >= 20 前端(Vite)与本地 API(tsx)
Python 3 3.10+ 子集化引擎(fontTools.subset)
fontTools / brotli 见 requirements.txt 由 npm run setup 自动装进 .venv

3. 安装与启动

# 1) 一键准备:创建 Python 虚拟环境并安装依赖 + 安装前端依赖
npm run setup

# 2) 同时启动前端(5173) 与 本地 API(5174)
npm run dev

启动成功后:

  • 前端界面:http://localhost:5173
  • 本地 API(无需手动访问):http://127.0.0.1:5174,已由 Vite 代理到 /api 与 /output

若你已手动建好 Python 环境,也可分步执行:

python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
npm install
npm run dev

4. 操作:把中文字体拆成全部分片

打开 http://localhost:5173,界面从左到右分四步。

步骤 01 · 加载字体

  • 拖拽或点击选择字体文件,支持:.ttf .otf .woff2 .ttc .otc
  • 文件只在本机磁盘落盘,不会上传到任何服务器
  • 加载成功后,右侧顶部会出现「字体预览」面板(用你上传的字体渲染一段可编辑文字 + 字号滑块)

.ttc / .otc 是字体集合,默认取首个字形面(fontNumber = 0)。

步骤 02 · 你的网站会出现哪些字

决定「切哪些字」:把网站的正文、导航、标题、按钮文案粘贴进来即可。 工具会按字去重并统计字数。

  • 默认就是「拆分全量字体」:开关默认开启,工具会直接用字体 cmap 的全部码位出片, 绕过兜底字表上限,生僻字 / 扩展区 / 符号一律切出(此时下方文案输入框与兜底字表隐藏、不生效)。 想改为「只切网站实际用到的字」,关闭该开关即可,输入框会重新出现。
  • 留空也可以:此时只用下方「兜底字表」来选字(见步骤 03)。
  • 展开「我想预测单个页面的加载量」可粘贴某一个页面的文案,仅用于模拟首屏下载量, 不会改变产物。

步骤 03 · 分片策略

配置项 说明 默认值
输出格式 woff2(默认,体积小)/ woff(兼容老浏览器)/ ttf(非 Web 场景),可多选 woff2
分片模式 见下 混合
单片字数 (baseSize) 每片基准字数 200
递增系数 (growth) >1 时低频片更大;1 = 等大小片 1.35
单片上限 (maxSize) 单片的字数上限 800
兜底字表 站点未覆盖的字,按通用字频补全 常用字前 3500

三种分片模式:

  • 混合:站点用字优先排前,字频表兜底补全生僻字。兼顾二者,适合大多数站点。
  • 字频:完全按通用字频降序切分。适合内容不可预知的博客、CMS、UGC。
  • 站点:只打包你粘贴到的字符。适合文案固定的落地页、活动页(此时兜底被强制关闭)。

步骤 04 · 生成分片

点击左下角 「生成分片」 按钮,右侧即出现结果。


5. 结果解读

右侧会依次展示:

  • 体积对比:原始字体大小 → 分片合计 →(若填了样本文本)模拟首屏实际下载量,三级对比。
  • 实时校验:在「分片策略」面板里,参数一改即时提示合理性(如频率模式需选兜底字表、单片上限过大、字符集超出字体字形数将缺字回退等),仅提示不阻止。
  • 分片清单:
    • 每片显示序号 #、字数、覆盖的字符样本(鼠标悬停查看精确 unicode-range)、文件大小;
    • 高亮行 = 样本文本会命中的片;
    • 每片行内可下载该片的各格式产物文件(woff2 / woff / ttf),底部提供「下载全部」(详见第 8 节)。
  • 产物预览:可直接复制或下载的 @font-face CSS(见第 6 节部署)。

6. 获取产物并部署

生成的分片文件写在本地磁盘的:

output/<jobId>/
  ├── font-0.woff2
  ├── font-1.woff2
  ├── ...
  └── font-N.woff2

当前界面没有「下载 zip」按钮,产物直接落在本项目的 output/ 目录,从那里取即可。

部署步骤:

  1. 复制「产物预览」面板里的整段 CSS;
  2. 把 output/<jobId>/ 整个文件夹上传到你的站点(与 CSS 中引用的路径一致);
  3. 在你的页面 <head> 引入这段 CSS。

CSS 示例(已自动生成,unicode-range 让浏览器按需下载):

@font-face {
  font-family: 'YourFont';
  src: url('/output/<jobId>/font-0.woff2') format('woff2');
  font-display: swap;
  unicode-range: U+4E00-4E7F, U+4E80-4EFF, ...;
}
/* ……每个分片一段…… */

生产环境请把 CSS 里的 /output/<jobId>/ 前缀替换为你实际放置字体文件的 URL 路径 (例如 https://cdn.example.com/fonts/yourfont/)。

打包成 zip(可选):

cd output/<jobId>
zip -r ../../yourfont-chunks.zip .

7. 想「覆盖字体里尽可能多的字 / 拆成全部分片」

工具按字符集切分,字符集 = 你粘贴的文案 + 兜底字表(自动与字体实际支持的码位取交集)+ ASCII/标点保底。 字体里没有的字会被自动跳过(不会报错,也不会产出对应字形)。

目标 推荐设置
拆出字体里的每一个字形(全部分片) 步骤 02 的 「拆分全量字体」 开关(默认开启)
覆盖常见中文全部(GB2312,6763 字) 模式选 混合 或 字频;兜底字表选 GB2312 全集
覆盖常用 3500 / 7000 字 兜底字表选 常用字前 3500 / 7000
只切网站实际用字 模式选 站点,并把网站文案粘进步骤 02
覆盖字体里更多字形(GBK、生僻字、Unicode 扩展等) 把完整字符清单粘贴进步骤 02 文案框;内置表最高到 GB2312

要点:

  • 「站点」模式只切你粘贴的字、不补兜底,不适合「全部分片」场景。
  • 注意内置字频表上限:当前内置字频表只有约 1766 字(近似数据,详见 src/core/assets/charfreq-zh.ts 文件头说明),因此即便选「GB2312 全集(6763)」, 实际最多也只能补到约 1766 字。要真正拆出字体里的全部字形,请用 「拆分全量字体」 开关。
  • 全量模式 = 字体 cmap 的全部码位,无需粘贴任何文案,是「拆成全部分片」最简单的方式。
  • 全量模式 / GB2312 全集都会与字体 cmap 取交集,只会切字体里确实包含的字,避免产生空片。

8. 下载分片产物

  • 逐片下载:每片行内可下载该片的各格式产物文件(woff2 / woff / ttf)。
  • 下载全部:底部「下载全部」一次性打包所有分片文件与 @font-face CSS 为 .zip。

9. 目录结构(速览)

src/
  web/            前端界面(React + Vite)
  api/            本地 API 服务(上传 / 检视 / 处理 / 读盘)
  adapters/       Node ↔ Python 引擎适配(fontEngine / pipeline)
  engine/         Python 子集化引擎(fontTools.subset,两阶段提速)
  core/           纯函数:字符集、分片、模拟、校验(validate)
demo/             示例字体(可拖入试用)
output/           生成的分片产物落盘处

10. 常见问题

  • 字体不出本机吗? 是。全部在本地 npm run dev 进程内完成,文件只读写本机磁盘。
  • .ttc / .otc 为什么只切出一部分字? 集合体默认取首个字形面,可在代码/接口传入 fontNumber 切换。
  • 为什么产物里没有某个字? 该字不在你提供的字符集(文案 + 兜底)与字体 cmap 的交集中; 扩大兜底字表或补充文案即可。
  • Python 报错 No module named fontTools? 确认已执行 npm run setup(或手动在 .venv 里 pip install -r requirements.txt)。

11. 命令速查

命令 作用
npm run setup 建 .venv + 装 Python 依赖 + npm install
npm run dev 启动前端(5173) 与 API(5174)
npm run dev:web / npm run dev:api 仅启动前端 / 仅启动 API
npm run build 类型检查 + 构建
npm run test 运行单元测试
npm run typecheck 仅类型检查

12. English (quick start)

Zitrange subsets and splits CJK / Chinese webfonts into small woff2 chunks by unicode-range, then generates ready-to-paste @font-face CSS, so the browser downloads only the glyphs a page actually uses. Everything runs locally — your font files never leave the machine.

npm run setup   # .venv + fontTools / brotli + npm install
npm run dev     # web UI on :5173, local API on :5174
  1. Load a font — .ttf .otf .woff2 .ttc .otc.
  2. Pick the character set — paste your site copy, or keep split the whole font (font cmap) on.
  3. Choose a strategy preset — smallest size / balanced / fewest requests. Advanced knobs (ordering mode, fallback charset, ASCII first-slice) live in a collapsed section.
  4. Generate — compare sizes, inspect every chunk, copy the @font-face CSS, download chunks one by one or as a single .zip. Output is written to output/<jobId>/.

13. Keywords / 关键词

English: font subsetting · webfont subsetting · CJK font · Chinese webfont · font splitting · font chunking · unicode-range · woff2 · fontTools · pyftsubset · web performance · self-hosted

中文:中文字体分包 · 字体子集化 · 字体切割 · 中文 Web 字体优化 · webfont 压缩 · 按需加载字体 · 字体分片

同类:font-spider(字蛛)· fontmin · cn-font-split(中文网字计划)· pyftsubset


14. License

MIT © 2026 yuxing.wang

About

中文字体分包 / 子集化:按 unicode-range 把 CJK 字体切成 woff2 分片并生成 @font-face,浏览器只下载用到的字。纯本地运行 | Chinese webfont subsetting & splitting

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages