在现代前端开发中,提升网页首屏加载速度和用户体验是非常重要的目标。本文将介绍三个简单但高效的优化技巧。

一、CSS media="print" 异步加载法

原理

通常,浏览器在遇到 <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),关键样式建议仍同步加载,避免页面“无样式”闪烁。

二、JavaScript 的 defer 属性

原理

默认情况下,浏览器遇到 <script src="...">阻塞 HTML 解析,直到脚本下载并执行完毕。这样会影响页面内容的及时显示。

加上 defer 属性后,脚本会在 HTML 解析完成后再执行,不会阻塞页面渲染。适合页面功能性脚本、第三方库等。

示例代码

<script src="main.js" defer></script>

适用场景

  • 绝大多数页面 JS(如交互、动画、第三方库等)
  • 只要不是必须在 <head> 立即执行的脚本,都推荐加 defer

注意事项

  • defer 只对外部脚本有效(即有 src<script>

async的关系

  1. async
  • 下载:脚本会并行下载(不阻塞 HTML 解析)。
  • 执行:一旦下载完成,立刻执行(哪怕 HTML 还没解析完)。
  • 执行顺序:多个 async 脚本互相独立,谁先下载完谁先执行,顺序不确定。
  1. 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-faceswap属性代表先用回退字体渲染,等字体加载好再替换,避免“白屏文字缺失”(FOIT)。同时也可以采用fallback / optional:让浏览器在网络差时甚至可以放弃加载字体,加快首屏。

当然,如果你想严格控制字体加载时间,可以尝试 Font Loading API,不过在这不过多介绍。

document.fonts.load("1em Sarasa").then(() => {
  document.documentElement.classList.add("font-loaded");
});

以上代码可以让页面先用系统字体渲染,等字体真正加载好后,再切换 CSS class 应用自定义字体。还可以自定义“加载中”的占位体验。

参考资料

标签:无

你的评论