改进整个 JavaScript 生态系统中的 Largest Contentful Paint。
作为 Aurora 项目的一部分,Google 一直致力于 框架,以确保它们根据核心网页指标表现良好。Angular 和 Next.js 已实现字体内嵌功能,这在本文的第一部分中进行了说明。第二个 优化,我们将介绍关键的 CSS 内联功能,Angular CLI 中现已默认启用 CSS 内联功能 并且目前正在 Nuxt.js 中实现。
字体内嵌
在对数百款应用进行分析后,Aurora 团队发现开发者通常会将字体
通过在 index.html
的 <head>
元素中引用它们来实现。下面是一个示例
添加 Material 图标后的显示效果:
<!doctype html>
<html lang="en">
<head>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
...
</html>
虽然此模式完全有效且功能正常,但它会阻止应用的渲染 并引入一个额外请求。为了更好地了解具体情况,请查看源代码 上述 HTML 中引用的样式表的代码:
/* fallback */
@font-face {
font-family: 'Material Icons';
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/font.woff2) format('woff2');
}
.material-icons {
/*...*/
}
请注意 font-face
定义如何引用 fonts.gstatic.com
上托管的外部文件。
加载应用时,浏览器首先必须下载引用的原始样式表
接下来,浏览器下载了 woff2
文件,最后才能够继续渲染
应用。
一个优化机会是在构建时下载初始样式表,并将其内嵌在
index.html
。这样可在运行时跳过到 CDN 的整个往返,从而缩短阻塞时间。
构建应用时,系统会将请求发送到 CDN,从而提取样式表并内嵌
将它添加到 HTML 文件中,并向网域添加 <link rel=preconnect>
。通过应用这种方法,
将得到以下结果:
<!doctype html>
<html lang="en">
<head>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin >
<style type="text/css">
@font-face{font-family:'Material Icons';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/font.woff2) format('woff2');}.material-icons{/*...*/}</style>
...
</html>
Next.js 和 Angular 中现已提供字体内嵌功能
当框架开发者在底层工具中实现优化时, 现有应用和新应用,从而为整个生态系统带来改善。
在 Next.js v10.2 和 Angular v11 中,此改进功能默认处于启用状态。两者均支持 内嵌 Google 和 Adobe 字体。Angular 预计会在 v12.2 中推出后者。
您可以在 GitHub 上找到 Next.js 字体内嵌的实现,还可以观看在 Angular 环境中解释这项优化的视频。
内嵌关键 CSS
另一项增强功能涉及通过内嵌关键 CSS 来提高 First Contentful Paint (FCP) 和 Largest Contentful Paint (LCP) 指标。网页的关键 CSS 包括 初始呈现时使用的所有样式如需详细了解该主题,请访问 推迟非关键 CSS。
我们发现,许多应用会同步加载样式,这会阻止应用
呈现。一种快速解决方法是异步加载样式。您不必使用
media="all"
时,将 media
属性的值设置为 print
,在加载完成后,
将属性值替换为 all
:
<link rel="stylesheet" href="..." media="print" onload="this.media='all'">
不过,这种做法会导致没有样式的内容闪烁。
<ph type="x-smartling-placeholder">上面的视频展示了如何呈现以异步方式加载其样式的网页。闪烁
这是因为浏览器首先开始下载样式,然后呈现
。浏览器下载样式后,就会触发 link 元素的 onload
事件,
将 media
属性更新为 all
,并将样式应用于 DOM。
在呈现 HTML 和应用样式期间,网页会部分取消样式。 当浏览器使用样式时,我们会看到闪烁,这不仅会造成糟糕的用户体验,还会导致 Cumulative Layout Shift (CLS) 中的回归问题。
关键的 CSS 内嵌以及异步样式加载可以提高 加载行为critters 工具可找出哪些样式 方法是查看样式表中的选择器并将其与 HTML 进行匹配。 找到匹配的样式后,它会将相应样式视为关键 CSS 的一部分,并且 。
让我们看看以下示例:
<head> <link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'"> </head> <body> <section> <button class="primary"></button> </section> </body>
/* styles.css */ section button.primary { /* ... */ } .list { /* ... */ }
在上面的示例中,动物将读取并解析 styles.css
的内容,然后解析
将两个选择器与 HTML 进行匹配,并发现我们使用了 section button.primary
。
最后,动物将在页面的 <head>
中内嵌相应的样式,从而生成:
<head> <link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'"> <style> section button.primary { /* ... */ } </style> </head> <body> <section> <button class="primary"></button> </section> </body>
在 HTML 中内嵌关键 CSS 后,您就会发现页面的闪烁问题已消失:
<ph type="x-smartling-placeholder">Angular 中现提供关键 CSS 内嵌功能,并且在 v12 中默认启用。如果您使用的是 v11
可以通过在 angular.json
中将 inlineCritical
属性设置为 true
来将其开启。接收者
在 Next.js 中选择启用这项功能,并将 experimental: { optimizeCss: true }
添加到 next.config.js
。
总结
在这篇博文中,我们谈到了 Chrome 和 Web 框架之间的一些协作。如果您是 框架作者,并认识到我们在你们的技术中解决的一些问题,希望我们的 可以启发您采用类似的效果优化措施。