文章内容

2022/6/9 18:48:48,作 者: 黄兵

异步加载 CSS 的最简单方法

为了提高页面性能和弹性,我们可以做的最有影响力的事情之一:是以不延迟页面呈现的方式加载 CSS。这是因为默认情况下,浏览器会同步加载外部CSS——在下载和解析 CSS 时停止所有页面渲染——这两者都会导致潜在的延迟。当然,在允许页面开始渲染之前,至少应该加载网站的一部分 CSS,并且要立即将初始 CSS 获取到浏览器,我们建议内联(或 HTTP2 服务器推送)CSS。对于整体数量较少的网站,仅此一项可能就足够了,但如果 CSS 很大(例如,大于 15 到 20kb),则可以通过优先级来提高性能。拆分后,应在后台加载不太重要的 CSS——AKA异步。在这篇文章中,我的目标是描述我们现在首选的方法,这种方法实际上已经存在多年了。


有几种方法可以使 CSS 异步加载,但没有一种方法能像您期望的那样直观。与script元素不同,没有async或defer属性可以简单地应用于link元素,因此多年来我们一直在维护loadCSS 项目,以使加载异步 CSS 的过程更容易一些。不过最近,浏览器已经标准化了它们的 CSS 加载行为,因此可能不再需要像 loadCSS 这样的专用脚本来处理它们的微小差异。


代码

今天,只要稍微了解一下浏览器是如何处理各种link元素属性的,我们就可以用一小行 HTML 实现异步加载 CSS 的效果。这是异步加载样式表的最简单方法:

<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">


说明

这行 HTML 很简洁,但不是很直观,所以让我们分解一下这里发生了什么。


首先,link的media属性设置为print。“print”是一种媒体type,它表示“将此样式表的规则应用于基于打印的媒体”,或者换句话说,当用户尝试打印页面时应用它们。诚然,我们希望我们的样式表适用于所有媒体(尤其是屏幕)而不仅仅是打印,而是通过声明与当前环境不匹配的媒体类型,我们可以实现一个有趣且有用的效果:浏览器将加载样式表不延迟页面渲染,异步!这很有帮助,但这并不是我们想要的全部。我们还希望 CSS 在加载后实际应用于屏幕环境。为此,我们可以使用该onload属性将link' 的媒体设置all为何时完成加载。


rel=preload不也可以这样做吗?

是的,同样!在过去的一两年里,我们一直在使用link[rel=preload]( 而不是rel=stylesheet) 来实现与上述类似的模式(分别rel在加载后切换属性而不是media属性)。使用这种方法仍然可以正常工作,但是在使用preload. 首先,浏览器对预加载的支持仍然不是很好,所以如果你想依靠它来跨浏览器获取和应用样式表,则需要一个 polyfill (例如:loadCSS 提供的那个)。更重要的是,preload很早就以最高优先级获取文件,可能会降低其他重要下载的优先级,这可能比非关键 CSS 实际需要的优先级更高。


幸运的是,如果您碰巧想要rel=preload提供的高优先级 fetch(在支持它的浏览器中),您可以将它与上述模式结合起来,如下所示:

<link rel="preload" href="/path/to/my.css" as="style">
<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">

鉴于上面代码的简单和声明性,我们会选择它而不是 polyfill,所以现在我们再次偏爱打印媒体切换方法。


为什么不使用虚假媒体属性?

过去几年一直关注我们的文章的任何人都可能记得,我们使用了“only x”之类的媒体属性值,通过提供一个与任何环境都不匹配的值来实现与“print”相同的效果,例如x是一种无意义的媒体类型。当浏览器遇到不匹配的媒体类型时,它们当前对待它们都是一样的——它们无论如何都会加载文件。也就是说,一些浏览器团队开始考虑区分不匹配的媒体类型和无效的媒体类型(或根本不被浏览器识别),并且可能不请求使用无效媒体类型链接的文件. 这会破坏很多现有的 CSS 加载实现,所以不太可能,但为了安全起见,我们建议使用有效的、不匹配的类型,如print。


你可能不需要 loadCSS... 

我们继续维护 loadCSS 并发现它在某些情况下很有用,特别是对于以编程方式从 JavaScript 获取 CSS 文件时,如下所示:loadCSS("/path/to/my.css"). 如果您已经在使用 loadCSS 或它的 polyfillrel=preload模式,则不一定需要更改任何内容。在内部,它使用本文中描述的相同机制。


但是,我们越来越多地发现,简单的 HTML 方法可能就是您所需要的。简单往往是最好的。


原文:The Simplest Way to Load CSS Asynchronously

分享到:

发表评论

评论列表