描述在 grunt 中实现字体子集化以支持多语言
解读
面试官真正想考察的是:
- 你是否理解“字体子集化”对多语言性能优化的意义:剔除未用字形,减少包体,缩短 FCP/LCP。
- 能否把Grunt 插件生态与国内常见语言场景(简体中文、繁体中文、日文、韩文、拉丁扩展、图标字体)结合起来,给出可落地的任务链。
- 是否具备工程化思维:配置一次,CI 自动跑,支持增量构建,出错可回滚。
- 对字体版权合规有没有意识,避免“拿方正/汉仪直接切”这类红线。
知识点
- grunt-webfont:把 SVG 图标批量生成图标字体,可配合 unicode-map 做码点去重。
- grunt-fontmin:国内阿里团队开源,基于 fontmin 核心,可扫描本地文件或远程模板中的字符,输出子集。
- grunt-unicode-db:生成 Unicode 范围正则,方便按语言区块(CJK Unified Ideographs、Hangul Syllables、Latin-1 Supplement)批量过滤。
- grunt-contrib-watch + grunt-contrib-connect:监听翻译文件变动,自动重跑子集任务并触发 Livereload,方便多语言同事并行调试。
- grunt-cache-bust:子集字体文件名加 hash,避免 CDN 缓存旧版本。
- 多语言字符来源最佳实践:
- 业务代码:扫描
src/**/*.{vue,jsx,ts,html}中的字面量。 - 翻译文件:扫描
locales/**/*.json,把 value 合并成字符池。 - 动态文案:若走接口,需把后端返回的高频词提前落库到白名单文本。
- 业务代码:扫描
- 版权红线:确认原字体授权允许Web 嵌入及修改生成衍生字体;国内大厂通常采购思源黑体、阿里巴巴普惠体、OPPO Sans,可放心子集化。
- 构建策略:
- 开发阶段:保留完整字体,方便新增文案。
- 提测/上线:CI 触发
grunt build:prod,自动切到子集。 - 增量优化:利用
grunt-newer,只重编变动的语言包。
答案
我之前的项目用 Grunt 做多语言门户,字体包体从 6.3 MB 压到 430 KB,核心思路分三步:
-
收集字符池
- 用
grunt-icontochar扫描图标组件,输出已用 icon 的 unicode 数组。 - 用
grunt-fontmin自带的text插件,把locales/**/*.json里所有文案合并成去重后的超大字符串。 - 再加一份产品名、运营活动关键词白名单,避免动态接口文案缺字。
- 用
-
生成子集字体
- 任务链:
grunt.registerTask('subset', ['fontmin:zhCN', 'fontmin:zhTW', 'fontmin:jaJP', 'fontmin:koKR'])。 - 每个 target 指定各自的 Unicode 范围:
fontmin: { zhCN: { options: { text: '<%= grunt.file.read("tmp/zhCN.txt") %>' }, src: 'src/fonts/AlibabaPuHuiTi-Regular.ttf', dest: 'dist/fonts/zhCN/' } } - 图标字体单独跑
webfont任务,与文本字体分离,避免混排导致的 baseline 异常。
- 任务链:
-
注入与缓存
- 用
grunt-replace把dist/index.html中的<link rel="preload">路径替换成带 hash 的新字体。 grunt-cache-bust给字体文件加 8 位 hash,Nginx 开启Cache-Control: max-age=31536000, immutable。- 最后
grunt-contrib-compress打成fonts-zhCN.gz,OSS 自动回源,移动端节省 30% 额外流量。
- 用
整个流程接入 GitLab CI,合并请求阶段跑 grunt subset --lang=all,若包体增长超 5% 会中断流水线,防止意外引入全量字符。
拓展思考
- 可变字体(Variable Font)+ 子集化:未来可把字重轴(wght)从 200-900 切成 3 档,再按语言子集,进一步省 20%-40%。
- 动态增量:若文案走 CMS,可在发布接口回调里触发 Lambda 版
fontmin,实时生成新子集并推送到边缘节点,实现“文案上线 30 秒内字体就绪”。 - 合规自动化:在 Gruntfile 里加
grunt-license-finder,扫描字体目录授权文件,若缺失则中断构建,避免法务风险。 - 性能衡量:把
/dist/fonts/*.woff2加入 WebPageTest 的“自定义指标”,子集化前后对比字形加载时间(Glyph Load Time),用数据说服老板继续投入工程化资源。