前端字体大小解决方案——字体切片
前端字体文件过大问题
在中文网站中,字体文件往往是最大的文件,每次请求网站都会下载字体文件,这样会导致网站加载速度变慢,影响用户体验。
在这方面,谷歌字体使用字体“切片”技术,将字体文件切割成多个小文件,使用 unicode-range
按需加载,这样可以减少字体文件的大小,提高网站加载速度。
unicode-range
unicode-range
是 CSS3 中的一个属性,用于指定字体文件中包含的字符范围,浏览器会根据这个属性来判断是否需要下载字体文件。
unicode-range
属性的值可以是一个或多个范围,每个范围之间用逗号分隔,每个范围可以是一个或多个字符,每个字符之间用连字符分隔。
例如引入谷歌字体的 Noto Sans SC
,可以使用以下代码:
@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;
}
...
字体切片
字体切片是指将字体文件切割成多个小文件,每个文件包含不同的字符,这样可以减少字体文件的大小,提高网站加载速度。
谷歌采用机器学习等手段,将字体文件切割成多个小文件,每个文件包含不同的字符,这样的话,一般网页中使用到的中文也只是一部分字体,只需要加载多个资源包就能完全覆盖。就算网页中有很多生僻字,需要付出的代价也只是多加载几个资源包。
字体切片工具
将中文字体按照 Google Fonts 的切割子集方案,生成多个较小体积的资源包。仅需加载小部分字体资源即可展示完整页面。
字体切片使用
安装
npm install --save-dev font-slice
# or
yarn add -D font-slice
使用
const fontSlice = require('font-slice');
const createFontSlice = require('font-slice');
createFontSlice({
// 字体文件
fontPath: path.resolve(__dirname, 'YourFont.ttf'),
// 输出文件夹
outputDir: path.resolve(__dirname, './output'),
})
这是一个简单的使用示例。使用 NodeJS 运行此文件,即可在 ./output
文件夹中生成切片后的字体文件,同时有一个 CSS 文件,可直接调用 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;
};