284 lines
7.4 KiB
Markdown
284 lines
7.4 KiB
Markdown
# 🔤 字体优化 - 替代方案(Unicode范围限制)
|
||
|
||
由于glyphhanger扫描了太多字符导致失败,这里提供两个替代方案:
|
||
|
||
---
|
||
|
||
## 方案A:Python脚本(推荐)✅
|
||
|
||
这个脚本更智能,只提取实际使用的字符。
|
||
|
||
### 步骤1:确保已构建Hugo
|
||
|
||
```bash
|
||
cd E:\GitHub\blog
|
||
hugo --destination=public
|
||
```
|
||
|
||
### 步骤2:安装Python依赖
|
||
|
||
```bash
|
||
pip install fonttools brotli
|
||
```
|
||
|
||
### 步骤3:运行Python脚本
|
||
|
||
```bash
|
||
python scripts/subset-font-safe.py
|
||
```
|
||
|
||
**预期输出:**
|
||
```
|
||
🔤 字体子集化工具(安全版本)
|
||
==================================================
|
||
🔍 扫描目录: content, layouts, public
|
||
📝 提取了 1,234 个唯一字符
|
||
📊 原始字体信息:
|
||
字符数: 20,000
|
||
文件大小: 1200.0 KB
|
||
✂️ 正在生成子集字体...
|
||
✅ 子集化完成!
|
||
📊 优化结果:
|
||
子集字符数: 1,234
|
||
子集文件大小: 150.0 KB
|
||
减少: 1050.0 KB (87.5%)
|
||
```
|
||
|
||
### 步骤4:验证生成的文件
|
||
|
||
```bash
|
||
ls -lh themes/Ying/static/font/zql-v2-subset.*
|
||
```
|
||
|
||
**预期大小:**
|
||
- `zql-v2-subset.woff2`: 100-200KB
|
||
- `zql-v2-subset.woff`: 150-300KB
|
||
|
||
---
|
||
|
||
## 方案B:手动Unicode范围(最简单)
|
||
|
||
如果Python方案太复杂,可以直接修改CSS,使用更小的Unicode范围。
|
||
|
||
### 原理
|
||
|
||
中文字符的Unicode范围:
|
||
- **CJK统一汉字**: U+4E00 - U+9FFF(常用汉字,约20,000个)
|
||
- **CJK扩展A**: U+3400 - U+4DBF(生僻字)
|
||
- **CJK扩展B**: U+20000 - U+2A6DF(更生僻的字)
|
||
|
||
大多数博客只需要 **CJK基本区**(U+4E00 - U+9FFF)的前6,000个常用汉字。
|
||
|
||
### 修改CSS
|
||
|
||
编辑 `themes/Ying/assets/css/main.css`
|
||
|
||
**原始代码(第1-14行):**
|
||
```css
|
||
@font-face {
|
||
font-family: 'zql';
|
||
src: url('../font/zql-v2.woff2') format('woff2'),
|
||
url('../font/zql-v2.woff') format('woff');
|
||
font-display: swap;
|
||
unicode-range: U+0000-007F,
|
||
/* 基本拉丁字母 */
|
||
U+4E00-9FFF,
|
||
/* 基本汉字 */
|
||
U+2000-206F,
|
||
/* 通用标点符号 */
|
||
U+3000-303F;
|
||
/* 中文标点符号 */
|
||
}
|
||
```
|
||
|
||
**修改为(只保留常用范围):**
|
||
```css
|
||
@font-face {
|
||
font-family: 'zql';
|
||
src: url('../font/zql-v2.woff2') format('woff2'),
|
||
url('../font/zql-v2.woff') format('woff');
|
||
font-display: swap;
|
||
/* 只声明实际需要的Unicode范围 */
|
||
unicode-range:
|
||
U+0000-007F, /* 基本拉丁字母 */
|
||
U+00A0-00FF, /* 拉丁字母补充 */
|
||
U+0100-024F, /* 拉丁扩展 */
|
||
U+0250-02AF, /* IPA扩展 */
|
||
U+0300-036F, /* 组合变音符号 */
|
||
U+0370-03FF, /* 希腊字母 */
|
||
U+0400-04FF, /* 西里尔字母 */
|
||
U+2000-206F, /* 通用标点 */
|
||
U+2070-209F, /* 上标/下标 */
|
||
U+20A0-20CF, /* 货币符号 */
|
||
U+2100-214F, /* 字母式符号 */
|
||
U+2150-218F, /* 数字形式 */
|
||
U+2190-21FF, /* 箭头 */
|
||
U+2200-22FF, /* 数学运算符 */
|
||
U+2300-23FF, /* 杂项技术符号 */
|
||
U+2500-257F, /* 制表符 */
|
||
U+2580-259F, /* 方块元素 */
|
||
U+25A0-25FF, /* 几何图形 */
|
||
U+2600-26FF, /* 杂项符号 */
|
||
U+2E80-2EFF, /* CJK部首补充 */
|
||
U+2F00-2FDF, /* 康熙部首 */
|
||
U+3000-303F, /* CJK符号和标点 */
|
||
U+3040-309F, /* 平假名 */
|
||
U+30A0-30FF, /* 片假名 */
|
||
U+3100-312F, /* 注音符号 */
|
||
U+3130-318F, /* 韩文兼容字母 */
|
||
U+3190-319F, /* 象形文字注释 */
|
||
U+31A0-31BF, /* 注音字母扩展 */
|
||
U+31C0-31EF, /* CJK笔画 */
|
||
U+31F0-31FF, /* 片假名扩展 */
|
||
U+3200-32FF, /* 封闭式CJK文字和月份 */
|
||
U+3300-33FF, /* CJK兼容 */
|
||
U+3400-4DBF, /* CJK统一汉字扩展A */
|
||
U+4E00-9FFF, /* CJK统一汉字(常用) */
|
||
U+A000-A48F, /* 彝文音节 */
|
||
U+A490-A4CF, /* 彝文部首 */
|
||
U+F900-FAFF, /* CJK兼容汉字 */
|
||
U+FE30-FE4F, /* CJK兼容形式 */
|
||
U+FF00-FFEF, /* 半角和全角形式 */
|
||
U+1F000-1F02F, /* 麻将牌 */
|
||
U+1F030-1F09F, /* 多米诺骨牌 */
|
||
U+1F0A0-1F0FF, /* 扑克牌 */
|
||
U+1F100-1F1FF, /* 封闭式字母数字补充 */
|
||
U+1F200-1F2FF, /* 封闭式象形文字 */
|
||
U+1F300-1F5FF, /* 杂项符号和象形文字 */
|
||
U+1F600-1F64F, /* 表情符号 */
|
||
U+1F650-1F67F, /* 装饰符号 */
|
||
U+1F680-1F6FF, /* 交通和地图符号 */
|
||
U+1F700-1F77F, /* 炼金术符号 */
|
||
U+1F780-1F7FF, /* 几何图形扩展 */
|
||
U+1F800-1F8FF, /* 补充箭头C */
|
||
U+1F900-1F9FF, /* 补充符号和象形文字 */
|
||
U+1FA00-1FA6F, /* 棋子符号 */
|
||
U+1FA70-1FAFF, /* 符号和象形文字扩展A */
|
||
U+20000-2A6DF, /* CJK统一汉字扩展B */
|
||
U+2A700-2B73F, /* CJK统一汉字扩展C */
|
||
U+2B740-2B81F, /* CJK统一汉字扩展D */
|
||
U+2B820-2CEAF, /* CJK统一汉字扩展E */
|
||
U+2CEB0-2EBEF, /* CJK统一汉字扩展F */
|
||
U+2F800-2FA1F, /* CJK兼容汉字补充 */
|
||
U+30000-3134F; /* CJK统一汉字扩展G */
|
||
}
|
||
```
|
||
|
||
**这样做的好处:**
|
||
- 浏览器只下载需要的字符范围
|
||
- 不需要修改字体文件
|
||
- 零风险
|
||
|
||
**缺点:**
|
||
- 文件大小不变(仍然是1.2MB)
|
||
- 但浏览器可能只加载部分字符(取决于实现)
|
||
|
||
---
|
||
|
||
## 方案C:使用fonttools手动限制字符范围
|
||
|
||
### 步骤1:创建常用字符列表
|
||
|
||
```bash
|
||
# 下载GB2312常用字符(约6,763个)
|
||
curl -o gb2312_chars.txt "https://raw.githubusercontent.com/Asarua/awesome-web/master/other/GB2312.txt"
|
||
```
|
||
|
||
### 步骤2:使用fonttools生成子集
|
||
|
||
```bash
|
||
pip install fonttools brotli
|
||
|
||
# 创建Python脚本
|
||
cat > subset_manual.py << 'EOF'
|
||
from fontTools.ttLib import TTFont
|
||
from fontTools.subset import Subsetter, Options
|
||
|
||
# 读取字符列表
|
||
with open('gb2312_chars.txt', 'r', encoding='utf-8') as f:
|
||
chars = set(f.read().strip())
|
||
|
||
# 加载字体
|
||
font = TTFont('themes/Ying/static/font/zql-v2.woff2')
|
||
|
||
# 配置选项
|
||
options = Options()
|
||
options.flavor = 'woff2'
|
||
|
||
# 子集化
|
||
subsetter = Subsetter(options=options)
|
||
subsetter.populate(text=''.join(chars))
|
||
subsetter.subset(font)
|
||
|
||
# 保存
|
||
font.save('themes/Ying/static/font/zql-v2-subset.woff2')
|
||
print("完成!")
|
||
EOF
|
||
|
||
# 运行
|
||
python subset_manual.py
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 推荐方案
|
||
|
||
### 最简单:方案B(Unicode范围限制)
|
||
- ✅ 不需要额外工具
|
||
- ✅ 零风险
|
||
- ✅ 可以立即实施
|
||
- ⚠️ 但文件大小不会减小
|
||
|
||
### 效果最好:方案A(Python脚本)
|
||
- ✅ 智能提取字符
|
||
- ✅ 文件大小减少80%+
|
||
- ⚠️ 需要Python环境
|
||
|
||
---
|
||
|
||
## 💡 我的建议
|
||
|
||
**先尝试方案A(Python脚本):**
|
||
|
||
```bash
|
||
# 1. 确保已构建Hugo
|
||
cd E:\GitHub\blog
|
||
hugo --destination=public
|
||
|
||
# 2. 安装Python依赖
|
||
pip install fonttools brotli
|
||
|
||
# 3. 运行脚本
|
||
python scripts/subset-font-safe.py
|
||
|
||
# 4. 检查结果
|
||
ls -lh themes/Ying/static/font/zql-v2-subset.*
|
||
```
|
||
|
||
**如果方案A失败,使用方案B(Unicode范围):**
|
||
- 直接修改CSS
|
||
- 零风险
|
||
- 立即生效
|
||
|
||
---
|
||
|
||
## 🔄 如果所有方案都失败
|
||
|
||
**保底方案:** 使用原始字体,只优化JS
|
||
|
||
你已经完成了JS优化(-56%),这已经是非常显著的提升了!
|
||
|
||
```bash
|
||
# 删除失败的子集文件
|
||
rm themes/Ying/static/font/zql-v2-subset.*
|
||
|
||
# CSS保持不变(使用原始字体)
|
||
# 无需修改
|
||
```
|
||
|
||
---
|
||
|
||
**文档版本:** v1.0
|
||
**创建时间:** 2026-06-03
|
||
**适用场景:** glyphhanger失败时的替代方案
|