提升网页首屏体验的HTML资源加载技巧
在现代前端开发中,提升网页首屏加载速度和用户体验是非常重要的目标。本文将介绍三个简单但高效的优化技巧。
media="print"
异步加载法
一、CSS 原理
通常,浏览器在遇到 <link rel="stylesheet" href="...">
时,会阻塞页面渲染,直到 CSS 下载并解析完毕。这样虽然保证了样式的完整性,但会拖慢首屏内容的显示。
通过设置 media="print"
,浏览器会认为这份 CSS 只在打印时才需要,因此不会阻塞页面渲染,而是异步下载。等 CSS 下载完成后,再通过 onload
事件把 media
改回 all
,样式立即应用到页面。
示例代码
<link rel="stylesheet" href="style.css" media="print" onload="this.media='all'">
适用场景
- 第三方样式库(如字体、动画、组件库等)
- 非关键样式(不影响首屏布局和内容的 CSS),关键样式建议仍同步加载,避免页面“无样式”闪烁。
defer
属性
二、JavaScript 的 原理
默认情况下,浏览器遇到 <script src="...">
会阻塞 HTML 解析,直到脚本下载并执行完毕。这样会影响页面内容的及时显示。
加上 defer
属性后,脚本会在 HTML 解析完成后再执行,不会阻塞页面渲染。适合页面功能性脚本、第三方库等。
示例代码
<script src="main.js" defer></script>
适用场景
- 绝大多数页面 JS(如交互、动画、第三方库等)
- 只要不是必须在
<head>
立即执行的脚本,都推荐加defer
注意事项
defer
只对外部脚本有效(即有src
的<script>
)
和
async
的关系
- async
- 下载:脚本会并行下载(不阻塞 HTML 解析)。
- 执行:一旦下载完成,立刻执行(哪怕 HTML 还没解析完)。
- 执行顺序:多个 async 脚本互相独立,谁先下载完谁先执行,顺序不确定。
- defer
- 下载:脚本也会并行下载(不阻塞 HTML 解析)。
- 执行:等到 HTML 解析完成(DOMContentLoaded 之前)再顺序执行。
- 执行顺序:按 HTML 中的先后顺序执行。
@font-face
的 url 加载
三、有些语言可能会有很大的字符集,例如中文,这个时候,一个支持较完善的字体文件可能会到达 30 MB(例如本站使用的 Sarasa Gothic)。如果直接在 <head>
里写style,浏览器会在解析 CSS 时立刻发起下载请求,这不仅可能阻塞首屏文字的渲染(导致一段时间“空白”),而且网络压力大时 UX 也会极差。如果你是用的link,那么可以使用上面的hack,或者可以使用兼容性更好(Safari除外)的
<link rel="preload" href="style.css" as="style" onload="this.rel='stylesheet'">
如果你用的是@font-face
那就另当别论了,可以用这个方法:
font-display: swap
例如:
@font-face {
font-family: 'Sarasa Gothic';
src: url('/fonts/sarasa-gothic.woff2') format('woff2');
font-display: swap;
}
这里font-face
的swap
属性代表先用回退字体渲染,等字体加载好再替换,避免“白屏文字缺失”(FOIT)。同时也可以采用fallback
/ optional
:让浏览器在网络差时甚至可以放弃加载字体,加快首屏。
当然,如果你想严格控制字体加载时间,可以尝试 Font Loading API,不过在这不过多介绍。
document.fonts.load("1em Sarasa").then(() => {
document.documentElement.classList.add("font-loaded");
});
以上代码可以让页面先用系统字体渲染,等字体真正加载好后,再切换 CSS class 应用自定义字体。还可以自定义“加载中”的占位体验。
参考资料
- MDN: link 标签 media 属性
- Google Developers: Efficiently load CSS
- MDN: script 标签 defer 属性
- Google Developers: Efficiently load JS
- 本文标题:提升网页首屏体验的HTML资源加载技巧
- 本文作者:uygnil
- 本文链接:https://blog.zhoulingyu.net/index.php/archives/21/
- 版权声明:本文采用 CC BY 4.0 协议进行许可
标签:无