面试题答案
一键面试拆分字体文件
- 原理:将大的字体文件拆分成多个小文件,浏览器可以并行加载这些小文件,从而提升整体加载速度,并且对于不需要全部字体字符的情况,减少不必要的加载。
- 实现方法:
- 使用
fonttools
等工具对字体文件进行子集化处理。例如,若项目只用到了部分中文字符,可以提取这些字符对应的字体数据生成新的字体文件。在Node.js环境中,可以安装fonttools
:npm install fonttools
,然后编写脚本对字体文件进行处理。 - 在Webpack中配置
url-loader
或file-loader
时,对字体文件输出路径进行设置,使其按规则拆分输出。比如,可以根据字体文件的类别或者字符范围来设置不同的输出目录。
- 使用
设置合适的加载策略
- 原理:根据字体的使用场景和优先级,选择合适的加载方式,确保关键字体优先加载,非关键字体延迟加载,减少首次渲染的阻塞。
- 实现方法:
- 关键字体预加载:在
html
的<head>
标签中使用<link rel="preload" as="font">
对关键字体进行预加载。例如:
- 关键字体预加载:在
<link rel="preload" href="path/to/your/font.woff2" as="font" type="font/woff2" crossorigin>
- 非关键字体延迟加载:利用
IntersectionObserver
结合JavaScript动态加载非关键字体。在Webpack构建的JavaScript模块中编写逻辑,当某个元素即将进入视口(或特定条件满足)时,使用document.createElement('link')
来加载字体文件。例如:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const link = document.createElement('link');
link.href = 'path/to/non - critical/font.woff2';
link.rel ='stylesheet';
document.head.appendChild(link);
observer.unobserve(entry.target);
}
});
});
const targetElement = document.getElementById('target - element');
if (targetElement) {
observer.observe(targetElement);
}
- 在Webpack的
css - loader
配置中,设置url
加载器的limit
参数,当字体文件小于该限制时,将字体转换为data URI
内联到CSS中,减少HTTP请求。例如:
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024 // 8kb,可根据实际调整
}
}
}
优化缓存
- 原理:合理设置缓存可以避免重复请求相同的字体文件,节省带宽和加载时间。
- 实现方法:
- 设置HTTP缓存头:在Web服务器(如Nginx或Apache)配置中,为字体文件设置较长的缓存时间。例如在Nginx中,可以在
location
块中设置:
- 设置HTTP缓存头:在Web服务器(如Nginx或Apache)配置中,为字体文件设置较长的缓存时间。例如在Nginx中,可以在
location ~* \.(woff|woff2|eot|ttf|otf)$ {
expires 365d;
access_log off;
}
- 版本控制:在Webpack配置中,使用
hash
或chunkhash
来为字体文件生成唯一的文件名。例如,通过file - loader
的name
参数设置:
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[contenthash:8].[ext]'
}
}
这样当字体文件内容发生变化时,文件名也会改变,浏览器会重新请求新文件,而内容未变时则会使用缓存。