slice chinese fonts into small slices.
将中文字体按照 Google Fonts 的切割子集方案,生成多个较小体积的资源包。仅需加载小部分字体资源即可展示完整页面。
- install font-slice
npm install --save-dev font-slice
yarn add -D font-slice
- usage
const path = require("path");
const createFontSlice = require('font-slice');
createFontSlice({
// fontPath
fontPath: path.resolve(__dirname, 'YourPath.ttf'),
// outputDir
outputDir: path.resolve(__dirname, './output'),
})
- 引用生成的 font.css 文件即可使用
declare type TOptions = {
/**
* 需要处理的源字体,暂只支持 ttf、otf (otf 也是先转成 ttf 再处理)
*/
fontPath: string;
/**
* 保存到的目录
*/
outputDir: string;
/**
* 是否需要在生成完成后打开预览页面,默认为 true,如果为 false 不会生成 index.html 及启动服务器
*/
preview?: boolean;
/**
* 生成字体文件的名称,默认为 `${fontFileName}.${index + 1}`
*/
generateFontSubsetName?: (fontFileName: string, index: number) => string;
/**
* 需要转换到的格式,默认为 ["woff2"]
*/
formats?: Array<'woff' | 'woff2' | 'ttf' | 'eot' | 'svg'>;
/**
* 字体的 font-family 值
*/
fontFamily?: string;
/**
* 字体的 font-weight,默认为 normal
*/
fontWeight?: string;
/**
* 字体的 fontStyle,默认为 normal
*/
fontStyle?: string;
/**
* 字体的 font-display,默认为 swap
*/
fontDisplay?: string;
/**
* 自定义字体的分割格式,默认为 google fonts 的 unicode-range
*/
customUnicodeRange?: Array<{
unicodes: number[];
}>;
/**
* 如果开启可能会让生成的字体体积变大,默认不开启
* keep ttf hint info (fpgm, prep, cvt). default = false
* https://github.com/ecomfe/fontmin#glyph
*/
hinting?: boolean;
};
-
默认的 font-display 为 swap,即在字体没有加载完成时,先使用别的字体展示。需要调整的话可以在传入的 options 里指明,更多 font-display 介绍请看这里
-
建议在 cdn 中将对应的字体目录直接设置一定时长的浏览器缓存,避免因字体加载导致页面内容闪动。
以得意黑字体为例为例
处理前 ttf 大小 2074KB,woff2 大小 928KB.
处理后每个类型的字体生成 95 个文件:
ttf 总大小为 2.3M (最小文件 3.4K,最大文件 55K)
woff2 总大小为 1.3M (最小文件 1.5K,最大文件 33K)
实际加载页面的体积由页面使用的字符决定,以该 README 为例,只需要加载 330KB 就能覆盖全部字符。
本工具使用 Google fonts 的 unicode-range 划分,来将一个完整的字体包分成多个小的资源包,在大部分情况下,只需要加载部分资源包就能完全覆盖。同时,当网页中有生僻字时,需要付出的代价也只是多加载几个资源包。
以谷歌字体的一个 css 引入文件为例:
@font-face {
font-family: 'Noto Sans SC';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/notosanssc/v12/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.4.woff2) format('woff2');
unicode-range: U+1f1e9-1f1f5, U+1f1f7-1f1ff, U+1f21a, U+1f232, U+1f234-1f237, U+1f250-1f251, U+1f300, U+1f302-1f308, U+1f30a-1f311, U+1f315, U+1f319-1f320, U+1f324, U+1f327, U+1f32a, U+1f32c-1f32d, U+1f330-1f357, U+1f359-1f37e;
}
/* [5] */
@font-face {
font-family: 'Noto Sans SC';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/notosanssc/v12/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.5.woff2) format('woff2');
unicode-range: U+fee3, U+fef3, U+ff03-ff04, U+ff07, U+ff0a, U+ff17-ff19, U+ff1c-ff1d, U+ff20-ff3a, U+ff3c, U+ff3e-ff5b, U+ff5d, U+ff61-ff65, U+ff67-ff6a, U+ff6c, U+ff6f-ff78, U+ff7a-ff7d, U+ff80-ff84, U+ff86, U+ff89-ff8e, U+ff92, U+ff97-ff9b, U+ff9d-ff9f, U+ffe0-ffe4, U+ffe6, U+ffe9, U+ffeb, U+ffed, U+fffc, U+1f004, U+1f170-1f171, U+1f192-1f195, U+1f198-1f19a, U+1f1e6-1f1e8;
}
该项目所做的内容如下:
-
提取 google fonts 的 unicode-range。
-
提取要处理的字体包含的所有字符,得到 google fonts 的 unicode-range 和字体里包含的字符的交集部分。
-
将字符按照上面步骤得出的拆分方案,提取字体子集,生成多个文件及 css 样式文件。