理解什么是“渲染阻塞资源”
当浏览器请求您的页面时,它需要正确地呈现任何出现在“折叠线”以上的HTML和CSS。
“折叠线”基本上是指在屏幕上可见且无需滚动即可看到的所有内容。
关键CSS是呈现折叠线以上内容所需的所有CSS。
如果您的网站使用JS进行渲染,则还需要使用与下面描述的用于水合/呈现初始页面内容的JS类似的技术。但是,此答案专注于CSS(原理相同,方法不同)。
为什么它很重要?
如果您的样式在外部样式表中,则浏览器必须执行以下操作:
- 下载页面的HTML。
- 查看渲染折叠线以上内容所需的样式。
- 下载所需的样式。
- 下载样式后才能呈现内容。
如果某人具有高延迟连接(例如4G,其中往返服务器的时间可能为300ms或更高),则这些额外的CSS网络请求可能会导致页面变慢。
相反,我们希望立即提供呈现折叠线以上内容所需的所有样式,以便不再需要进行网络请求。
修复步骤
原则很简单,但可能很难做到并需要耐心一点。
确定关键CSS
有许多方法可以做到这一点,但它们通常取决于您的构建过程、堆栈等。
然而,在原则上,您正在寻找一个工具,该工具将折叠线以上的HTML映射到与这些项目匹配的CSS类和样式。该工具应为您导出这些样式。
不幸的是,我尚未看到一个100%有效的工具,因此我建议您使用工具获取大部分样式,然后(在内联关键CSS之后-见下文)删除所有外部样式表,并查看是否存在无法正确呈现的内容。在包含外部CSS的页面上检查它们并将样式复制过来。
如果您没有考虑到这一点而且设计网站比较繁琐,但是值得投入时间和精力。
内联关键CSS
确定关键CSS后,您只需将其内联即可。
这只是意味着您需要压缩CSS并将其添加到页面顶部的<style>
标签中。
这回到我在介绍中提到的部分。一旦内联了所有样式,浏览器就拥有了呈现页面所需的一切内容,无需进行其他网络请求。这对您的“首次内容绘制”、“最大内容绘制”(通常)等非常有帮助。
延迟加载不必要的CSS
现在,您已经内联了关键CSS,只剩下两个步骤:
- 从样式表中删除关键CSS - 重复下载没有意义!
- 使用您在原始问题中展示的方法:
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>
这是它的工作原理:
- `
link rel="preload" as="style"
` 异步请求样式表。有关 preload 的更多信息,请参阅
预加载关键资源指南。
- 在
link
中使用的
onload
属性允许在CSS完成加载后处理它。
- 一旦使用了
onload
处理程序,“nulling”该处理程序可帮助某些浏览器避免在切换
rel
属性时重新调用处理程序。
- 在
noscript
元素内部对样式表进行引用,可以作为未执行JavaScript的浏览器的备用方案。
摘自
https://web.dev/defer-non-critical-css/
伪例子:
为了明确这一点,假设我们有一个简单的主区段网站,出现在折叠之上。只需要三个 CSS 类就可以使这个主区段正常工作,因此我们将其内联到 CSS 中。
<style>
.hero{
min-width: 100%;
height: 100vh;
background: #333;
}
.hero h1{
position: relative;
float: left;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #fff;
}
section{
width: 75%;
margin: 0 auto;
padding-top: 20px;
}
</style>
我们接着使用你描述的方法加载剩余的CSS:
<link rel="preload" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css"></noscript>
快速示例
<link rel="preload" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css"></noscript>
<style>
.hero{
min-width: 100%;
height: 100vh;
background: #333;
}
.hero h1{
position: relative;
float: left;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #fff;
}
section{
width: 75%;
margin: 0 auto;
padding-top: 20px;
}
</style>
<section class="hero">
<h1>Above the fold - all required styles inlined</h1>
</section>
<section class="below">
<h2>Below the fold, all classes in external style sheet</h2>
<p class="lead">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero. </p>
<p>Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. </p>
<p>Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. Quisque volutpat condimentum velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus consequat imperdiet. Vestibulum sapien. Proin quam. </p>
<p class="h4">Etiam ultrices. Suspendisse in justo eu magna luctus suscipit. Sed lectus. Integer euismod lacus luctus magna. Quisque cursus, metus vitae pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec, blandit vel, egestas et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices enim. </p>
<p>Curabitur sit amet mauris. Morbi in dui quis est pulvinar ullamcorper. Nulla facilisi. Integer lacinia sollicitudin massa. Cras metus. Sed aliquet risus a tortor. Integer id quam. Morbi mi. Quisque nisl felis, venenatis tristique, dignissim in, ultrices sit amet, augue. Proin sodales libero eget ante. Nulla quam. Aenean laoreet. </p>
</section>