价格昂贵的样式。Yandex报告

在页面上加载CSS是一项阻止操作。如果用户可能看不到JavaScript的异步加载,则样式的缓慢显示可能会导致网站上的客人不耐烦。如何为用户尽可能高效,无缝地加载CSS?Nikita Dubko试图弄清楚DarkMeFoDy 来自明斯克的Yandex搜索界面小组。


- 大家好。我会告诉您有关样式的信息。今天每个人都在谈论TypeScript和TypeScript。我将讨论Cascade样式脚本。

关于我自己不久。我是白俄罗斯的开发者-电影《杜迪》放映后,我会到处说。您可能在Web Standards播客中听到了我的声音,如果您在Web Standards新闻提要中看到错别字,也可能也是我。

小免责声明。报告中会有几项精神错乱-请大声批评对待我所说的一切。考虑一下为什么可以使用这种技术,以及为什么不需要它们。有些事情真的很疯狂。走。

做什么的?


首先-为什么要完全谈论CSS优化?

如果您开始在搜索引擎中寻找JS快速下载,则会有很多结果。如果您希望快速加载CSS,则顶部甚至不会显示所需的CSS。



如果您看一下Google,关于JS的搜索结果为1.11亿,关于CSS的搜索结果为2600万,

那么也许这并不重要?为什么要谈论它?如果您查找JS性能报告,则会发现很多。关于React,关于各种其他框架,关于Vanilla等。但是关于CSS,我只发现了一份报告。哈里·罗伯茨(Harry Roberts)在2018年阅读了有关CSS性能的精彩报告。我以为我找到了第二份报告Roma Dvornova撰写的“ Parsim CSS:性能提示和技巧”。但是事实证明这是解析CSS的JS报告。不完全是我们所需要的。

事实证明,他们对CSS的考虑不多。这是一个耻辱。

但是当我上网时,通常会看到HTML。而且我还看到了样式化页面的CSS。但是我看不到JS。 JS是在页面上移动CSS和HTML的东西,以使所有内容看起来都很漂亮。这是一个脚本。而且,如果不加载JS,就不如不加载CSS那样糟糕。

JS中的错误无声地落入控制台。而且普通用户不太可能进入DevTools进行查看:“哦,在那里,控制台中有错误。”但是,如果CSS无法加载,那么您可能根本看不到所需的一切。

顺便说一下,有一些关于事实的研究,即主要是给人留下第一印象。38%的用户可以访问该网站,如果他们看到它直接令人恶心,则将立即离开。而88%会容忍,用它一次,然后他们将永远不会回来,不太可能建议您的网站。

现在我们都坐在家里,互联网流量特别增加。我们需要考虑如何有效地将任何资源交付给用户。

让我们尝试从Yandex的角度进行计数。如果我们可以在100毫秒内优化每次Yandex交付并每天提供2亿页(我不知道确切的数字),那么这一天我们将节省0.1 s * 2亿= 232人日。仅通过优化100毫秒的输出即可。 CSS也这样做。

让我们玩一些侦探,了解如何充分利用加载样式。

测量!


最初的建议是始终测量所有内容。从理论上讲,进行优化是没有意义的。您可以假设优化适用于您的情况,但是实际的测量结果表明这种优化毫无意义。这是任何优化的最重要规则。来自HolyJS的SERP Velocity团队的Andrei Prokopyuk 我们如何做到这一点非常满意,我不再重复。

有哪些测量工具?

-如果要在或多或少的真实设备上进行测量,请使用WebPageTest,它速度较慢,但​​不如您的酷。我通常在那里测量。

-如果您使用基于Chromium的浏览器,则拥有Lighthouse。他像本地测量一样显示出相当不错的东西。

-如果您确定自己可以做所有事情,请转至DevTools的“性能”选项卡。它有很多细节,您可以启动自己的指标并进行分析。



自然,在Performance中,必须设置实际条件。您正坐在办公室里有很棒的Internet的漂亮笔记本电脑上,这里的一切都很棒,但是他们来找您说:“我很慢。”然后您说:“一切都对我有用。”不要这样。

始终尝试检查地铁或其他地方的用户如何使用您的网站。为此,您需要设置一个非常慢的Internet。还建议您减慢CPU的速度,因为有人可以从某些诺基亚3110来找您。他还需要显示该站点。

最重要:衡量真实用户。有这样一个度量标准,更确切地说,是一组完整的度量标准-RUM,真实用户监视。在这种情况下,您不是衡量代码中综合发生的事情,而是衡量生产中实际用户的指标。例如,从加载页面到操作。例如,动作是在浏览器中起作用的东西,或者甚至是单击某些重要元素的东西。

请记住,您不是为机器人而开发。灯塔中的Sotka-很棒,非常好。因此,您至少满足了Lighthouse设置的要求。但是有真正的用户,如果用户在Lighthouse中沉沉时无法看到页面,则说明您做错了。



有一些重要的指标需要重点关注。这是“第一内容油漆”,当第一内容出现在您可以执行操作的页面上时,请阅读。您可以在Chromium浏览器中发送此指标。



最近,您仍然可以查看最大的内容丰富的绘画。您经常会遇到媒体页面,例如,查看页面上的照片很重要。然后,您需要此特定指标。

CSS加载


最后,让我们继续介绍CSS的加载方式。接待处早已众所周知。有一个关键渲染路径,一个关键渲染路径。它与浏览器从发送资源请求到像素显示在用户屏幕上的过程有关。关于这一点,也有很多文章和报告。但是,让我们快速浏览一下此浏览器的工作方式。

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS —  </title>
    <link rel="stylesheet" href="/main.ac74gsac.css">
</head>

他开始下载HTML,看到标签。他逐渐解析它们,了解如何处理它们。负载。跨过链接。必须使用它。但是如何?首先,您需要下载它。下载速度慢。加载时,它将开始进一步分析页面。

 <!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS —  </title>
    <link rel="stylesheet" href="/main.ac74gsac.css">
</head>
<body>
    <h1>-!</h1>
</body>
</html>

如果它偶然发现另一个链接,则会再次被阻止并且不允许执行。阻止JS,阻止解析。直到它启动,它什么也不做。但随后它开始进一步工作。

<链接>


让我们深入探讨-访问链接时会发生什么?



记录我们去的地方是标准的。在某处有CSS样式。现在,将所有静态数据放在CDN上已经很流行。

去哪儿?


首先,浏览器需要了解去向。



他看到了URL,并且需要了解该URL-它是关于什么的?我们已经习惯了URL是站点标识符的事实。



但是实际上,我们需要获取此URL的IP地址,然后转到该IP地址处的真实物理计算机。



对于您的CDN,它将收到DNS中的一条记录,并且实际上将直接转到IP地址。在这种情况下如何加速?



一个疯狂的想法是减少用户到DNS服务器的距离。获取并移植用户。例如,要显示消息:“坐得更近”或“移动得更近”。

您可以立即在链接中指定IP地址。如果您可以立即通过IP地址给出结果,为什么我们需要寻找DNS,解析域?这是一种疯狂的方式,但是对于DDoS全局DNS服务器,它甚至可以为您节省。

而且我们可以摆脱获取IP地址的麻烦。



转到index.html或另一个文件,您已经知道要去的域名地址。在这种情况下,您可以将静态变量更靠近您的域,也就是该域本身,而不是将静态变量存储在单独的域或子域中。然后,DNS不需要解析,已经解析了。



我们想出了去哪里。但是我们可以提前为浏览器完成这些操作。例如,如果您的样式表是通过DOM树稍后加载的,则可以使用<link rel =“ dns-prefetch”>告诉浏览器“我还没有到那里,但是您会预热资源,以后肯定会需要它们”。

使用此条目,您告诉浏览器关闭并获取此DNS。当链接出现在代码中时,浏览器将已经知道该域的IP地址。您可以做这些初步的事情。例如,同样的事情,进入下一页之前,您肯定会去那里。

好的,浏览器知道去哪里。他需要了解如何去。

怎么去


我们正在观察协议。现在,当然,https是直接要求。包括搜索引擎在内的网站将以不完全安全的形式标记您不在https上的网站。

我发现了一系列有关董事会运作方式的惊人漫画https。但是我们是IT人员,我们喜欢很酷的复杂图表,而有趣的漫画太容易了。



在这里,我用自己的话说了https是如何工作的。首先,您从服务器获取SSL证书。然后,您必须在证书颁发机构检查证书。这些是特殊的服务器,知道什么是有效的,什么不是,可以提示浏览器:“是的,这里一切都很好,请使用此证书”。

接下来是用于服务器和客户端之间通信,使用不同密钥进行加密,解密的密钥的生成。如果从密码学的角度来看,这个过程很有趣。但是我们要加快速度。怎么样?



我们可以再次将用户转移到服务器附近。我们已经有一个DNS,现在可以将其更靠近证书颁发机构。并且放在这些服务器之间将是完美的。

您可以选择退出https,为什么我们需要它?我们花时间获取证书,加密,解密。并不是的。这是报告中最有害的建议,请不要这样做。 https是用户数据保护,如果没有https,http / 2将无法工作,而http / 2是另一种加快速度的方法。



还有OCSP装订技术。您可以在没有证书颁发机构的情况下验证证书。这可能更接近DevOps。您需要以某种方式配置服务器,以便它可以缓存证书颁发机构的响应并发给用户:“相信我,我的证书是真实的。”因此,我们至少可以节省去认证中心的步骤。

但有一个细微差别-在Chrome中,这种方法无法正常工作,而且时间长了。但是对于其他浏览器的用户,您可以加快此过程。

我已经说过两次了,有必要移植用户,并且这个想法是浮空的-将服务器移近用户。我还没有发现任何新东西给您。这是CDN,即分布式内容交付网络。这个想法是,您可以使用现成的sidienki,在资金和机会允许的范围内,独立创建自己的基础架构,并在全球范围内放置一堆服务器。但是您需要安排服务器,以便来自澳大利亚的用户访问澳大利亚服务器。在这里,光速作用在您身上,距离越短,电子通过它的速度就越快。

让我们深入研究。请求中还有什么其他情况?实际上,https只是http的包装。不只是一个很酷的包装。而且,甚至更深的地方,HTTP也是TCP / IP系列的要求。



如何在网络上发送数据包和字节,以便所有浏览器,客户端和服务器相互通信?客户端/服务器通过TCP / IP连接进行的第一件事是握手。

但在2020年,世卫组织建议避免握手。有这么酷的TCP Fast Open技术。您可以在握手时避免整个链条“你好,我是客户”-“你好,我是服务器”-“我相信你”-“而且我相信你。走”。您现在已经可以发送有用的数据。如果握手成功,则部分有用数据已通过。这是TCP快速打开。

拿什么?


让我们弄清楚客户端应该从服务器中提取什么。最主要的不是客户端从服务器那里获取东西,而是服务器将数据提供给客户端。然后,您可能会想到:用户代理。我可以从客户端获取User-Agent,找出用户已登录的浏览器。大概找出它是否不会欺骗我这个浏览器。

.example {
    display: -ms-grid;
    display: grid;
    -webkit-transition: all .5s;
    -o-transition: all .5s;
    transition: all .5s;
    -webkit-user-select: none;
       -moz-user-select: none;
        -ms-user-select: none;
            user-select: none;
    background: -webkit-gradient(linear, left top, left bottom, from(white), to(black));
    background: -o-linear-gradient(top, white, black);
    background: linear-gradient(to bottom, white, black);
}

假设他是从Firefox登录的。像往常一样,我有一个程序集,其中自动前缀固定器被连接在一起,它为我生成了一堆代码。是的,这是一种很酷的方法,任何地方都可以使用。但是我已经知道用户已经从Firefox登录。

为什么不关掉所有多余的东西呢?同意,行数少很多,我们发送的字节数少,这很酷。

我们有SERP的精简版Granny。Vitaly Kharisov谈到了她维塔尔Web标准日课程报告。它正是使用这种方法。我们可以生成多个捆绑包,然后以不同的方式将它们分发给不同的客户。它们的重量要轻得多,这是因为Firefox拥有自己的产品,WebKit拥有了自己的产品,并且可以正常工作,并且已经过验证。



进一步。我们很可能会处理用户的请求,我们知道此人已被授权并为其使用一些个人信息。我们应该从数据库中获取一些信息是合乎逻辑的。但不是所有的!静态事物对于任何用户而言都没有什么不同,它们是完全相同的。

James Akvuh读了一篇很酷的报道“服务器端渲染。自己做”。有什么意义?您已经知道您拥有HTML和对所有用户都相同的某种CSS。在获取任何数据之前,您可以从此静态数据生成输出,并立即从服务器流中发送最有用的数据。然后,获取数据,快速接收数据,将其转换为模板,然后提供给客户端。用户将已经看到有用的东西。



我们很久以前就已经实现了。在SERP的主搜索页面上,有两个阶段-预搜索和后搜索。预搜索是指当我们发送所有不需要了解哪个用户已登录的信息时。例如,我们已经可以给他戴帽子。

也就是说,我们有一个搜索栏,用户可以在加载其他所有内容之前开始使用它。这在连接缓慢时很有用。我们做到了,它有效。

我还谈到了http / 2。现代浏览器完全支持此功能,因此,如果您尚未在服务器上对其进行配置,请至少了解如何进行配置。

Server Push是一种很酷的技术,它说:“浏览器,我还没有告诉您您需要某种CSS。但是我确切知道需要什么。所以握住它,预装它。”





不难您需要在服务器上配置几个标头,所有内容将开始工作。如果浏览器不知道该标题,则什么都不会破坏,这是最美丽的。让我们进一步挖掘。 TCP协议我们已经讨论过:握手,发送字节。



握手后洗手。但是就TCP而言,我们开始转发字节,并且对算法进行了充分优化,以使客户端服务器不会处于空闲状态。

因此,首先发送某个数据段。默认情况下(您可以在设置中更改)为1460字节。服务器不会在一个网段上发送信息。他发送窗户。

第一个窗口是14600字节,十段。然后,如果连接良好,他便开始放大窗口。如果连接不良,则可能会缩小窗口。什么是重要的理解?有十个细分的第一个窗口,如果需要,您必须在其中适合整个站点。然后,内容的显示速度将达到最高。Vitaliy Kharisov 也阅读了有关此报告。是的,如果您关闭了某个网站,例如JS,则可以将您需要的所有内容都放在一个窗口中。

一个重要的细微差别。当您填充整个细分时,它就是一个细分。但是,如果仅发送一个额外的字节,则服务器仍将发送整个额外的段。



您可以做一个很酷的优化,将输出减少整整千字节,但是您在测量中看不到任何东西-也许正因为如此。尝试在几个部分上正常进行优化。

奇怪:我是一个排字工人,我告诉服务器这么复杂的事情。让我们更接近真实的CSS。

少运送


因此,我们向用户发送的内容更少,细分更少,出现的更快,用户很高兴。



缩小她全都参与了她的项目。有很多很棒的工具,webpack插件,gulp设置-通常,您会自己弄清楚。您可以手动自定义它,但是只有在您确定可以压缩比任何CSSO都更酷的CSS时,它才会出现。

记住要启用压缩。如果至少在2020年未启用gzip,则您肯定做错了,因为这是一种古老的压缩技术。一般来说,到2020年,是时候使用brotli了。这是在Chromium浏览器中略微减少输出的好方法。或者,如果您不想支持brotli,则至少可以尝试zopfli。

对于gzip来说,这是一种相当慢的压缩算法,它可以提供最佳的压缩结果,并且与常规gzip一样快地进行解压缩。因此,需要对zopfli进行明智地配置,并且仅在不需要动态输出数据时才使用。您可以使用zopfli算法将gzip存档程序配置为在组装过程中收集,并且实际上已经静态发送,实际上并非即时进行。这可以为您提供帮助。而且还要衡量结果。



所有这些算法都使用某种字典:在重复代码片段的基础上构建字典。但是有时他们会说:有必要内联,如果我们内联,那么我们就摆脱了请求。链接HTML中的所有CSS将非常快。诀窍是,当您分解样式和HTML时,gzip的工作效率会更高一些,因为字典是不同的,效率更高。

就我而言,我只是进入了引导页面,在那里链接了引导并比较了这两个版本。单个资源上的Gzip少了150个字节。是的,收益很小。在这里,您也需要测量所有内容。但是,在您的情况下,这可以例如将段数减少一个。

如何优化代码?我不是在谈论缩小。带走您在项目中不使用的内容。您很可能拥有永远不会在客户端上执行的代码。做什么的?



为了使它自动化,浏览器内置了特殊的选项卡,例如,在Chrome DevTools中,这是Coverage,它告诉您:“我没有使用此CSS或JS,您可以将其剪裁掉。”

但是您可能已经将鼠标悬停,聚焦,活动了,并且使用JS安装了某些东西。您需要模拟站点上所有可能的操作,只有这样,您才能确保可以剪切此CSS。克里斯·科耶尔(Chris Coyer)撰写了一篇很好的评论文章,内容涉及自动工具,该工具尝试将鼠标悬停在焦点上并完成所有工作。但是他得出的结论是不可能实现自动化。尚未解决。

Booking.com Anton Kholkin 有一份不错的报告,他们还试图删除大量旧代码。但是它们有一个特点:遗留代码来自外部项目。有必要将其删除。看看他们遇到了什么有趣的解决方案。

您自己可以尝试使用相同的Puppeteer,例如Chrome。您可以进行自动通过所有测试的测试,并尝试进行悬停,集中注意力。并使用相同的Coverage。

我的同事Vitya Khomyakov维克托·霍米亚科夫编写了自己的脚本,例如在页面上查找重复项和样式。只需拿,复制和粘贴。他将在控制台中给您写信:“似乎不需要此选择器。”直到仅在DevTools中输入。这很棒。



我真的很喜欢Firefox开发人员的工具的功能:可以看到似乎使用的样式的机会,但实际上浏览器并未应用它们。

例如,您可以设置display:inline,似乎此display:inline对设置大小没有意义。或垂直对齐,仅适用于内联或表单元格。到目前为止,我只在Firefox中看到它可以突出显示:“您不需要此行”。

在这里,您也需要小心:也许您使用此样式稍后粘贴该类。但是我认为这是一个很酷的功能。

现在问自己一个问题:您是否需要项目中的整个Bootstrap?放置您使用的所有CSS框架而不是Bootstrap。最有可能的是,您将Bootstrap用于网格和或多或少的常见元素,而您不需要一半的Bootstrap。

尝试正确使用该组件。几乎所有现代CSS框架都允许您使用源代码进行汇编,并仅选择所需的内容。这样可以大大减少CSS捆绑包的大小。

不要放弃未使用的东西。您可以使用构建级别的了解,即本页面将不使用此CSS,而不是寻找我的遗产。

例如,完整的BEM堆栈使您能够进行装配,这样,您已经给页面了,就可以构建将在页面上的BEM块的所有组件的树。 BEM允许您确定如果此块不在页面上,则无需加载此CSS。仅运送必要的物品。

甚至来自Google的人都说:使用BEM,它确实可以帮助您进行优化。

我不相信我会大声说出来,但是在这种情况下,CSS-in-JS似乎是一个好方法。当您编写独立的独立组件并仔细配置程序集或在运行时确定使用哪些块以及哪些块不使用时,您可以通过不将代码发送给客户端来摆脱查找遗留代码的问题。听起来很容易,但是需要纪律。在项目开始时请事先考虑一下。



还有什么其他选择?有点疯狂。在这段代码中,似乎不需要样式,因为我们使用了div-默认值已经是display:block。然后删除所有默认值吗?如果您在项目中确定可以肯定HTML标记不会再更改-请浏览器已经提供的默认值并删除它们。

样式少-好极了!但这又是一个疯狂的主意。 CSS不必了解HTML,因为它是一种样式。它是非常独立的,您必须将其连接到另一个项目,它应该在那里工作。是的,很难维护。更改标签-一切中断。如所承诺的疯狂想法。

使用变量。 CSS具有非常老的变量,例如currentColor。



通常会有一种模式:例如,您想要制作一个其文本和边框颜色相同的按钮。通过悬停,我们将它们都更改了。做什么的?



有一个currentColor变量,它从颜色中获取一个值,例如,将其放在边框上,代理此属性,然后通过悬停,通过焦点,通过激活任意更改任何一行,即可更改任何内容。这似乎很方便,并且代码减少了一行。您可以优化。顺便说一句,在此示例中,您根本不能使用border-color任务,因为默认情况下它已经从color属性中获取了一个值。

有时很伤心,观看如何Base64是使用。在CSS中,以前曾积极建议:使用base64注入小图标。如果它适合TCP的一个细分市场,那么对您有好处。



但是哈里·罗伯茨(Harry Roberts)也是对base64如何影响页面加载进行了经典研究。是的,请求较少,但此类样式的解析速度有时较慢。

好的,解析是非常快速的操作,用户很可能不会注意到。但是我们有一个重要的指标-第一个呈现,以便用户可以看到页面上的内容。根据哈里·罗伯茨(Harry Roberts)的一项研究,在手机上,第一次渲染发生在十次之后。考虑您是否需要base64?是的,请求较少,但是有效果吗?

并且,请勿将base64用于SVG。因为SVG非常适合使用URL编码器。朱莉娅·布赫瓦洛娃(Julia Bukhvalova)的工具很酷:进来,粘贴您的SVG,它将以准备好粘贴的形式提供CSS。您可能会注意到没有base64,但是有些事情发生了转义,即CSS可能无法正确识别。它效率更高。

平均而言,base64会使压缩的大小增加30%。做什么的?

使用现代技术。我们可能需要支持Internet Explorer-谈论网格时的常用参数。



但是请考虑一下:如果您不支持IE,并且仍在浮动字体或表格上进行排版,则可以使用网格进行间距为20像素的三列布局-这是列之间的距离。三行。好吧,五个,考虑公告本身。

尝试在浮动。我的意思是,如果您触摸HTML,我们将更改三行,包括类的名称。我没有找到一种方法可以在漂浮时做同样的酷。放弃您的决定。但是要使用现代技术。它们使您可以更紧凑地指示标记。



您可以尝试Atomic CSS。它是什么?您写这些有点疯狂的类名。一段时间后,您开始了解是由您来设置背景颜色还是仅设置颜色。这些是CSS的“功能”。但是您有一个固定的CSS集,然后可以在HTML中使用它来指示样式。 CSS突然变小了。对于大型项目,它的确会变小,因为独特的样式会更少。但是您正在增长HTML。



您可以朝着逐渐流行的Tailwind CSS的方向看。它不是Atomic CSS,而是关于实用程序类的,类似于Bootstrap,只是更具实用性。您可以使用特定的集。对于您来说足够了。一组执行其功能的类。您也可以尝试,但不要做得太多。



另一个疯狂的想法-为什么我们在客户端上需要完整的类名?是的,它对于开发和调试很方便,但是让我们采用所有的类名并将其命名为单个字母。它会更少。

这是有关如何执行此操作的文章。您可以在构建时配置webpack或其他插件。但这并没有从我们这里起飞。我们尝试了。

事实证明,gzip非常酷,以至于我们都对所有内容进行了优化,并且BEM和gzip非常友好。因为重复了文本构造来描述代码中的块和元素。

总的来说,这几乎没有给我们带来任何利润。但是,例如,如果您没有BEM和许多不同的类,则可以尝试。

重要:测量。测量所有这样的实验片。也许现在它对您有用,然后您稍稍更改了项目的体系结构,开始进行不同的组装,一切都变慢了。

下载它!


到目前为止,我仅讨论了如何下载文件。我们下载了它。用户一直都在看什么?



他看到了如此惊人的屏幕。在我们下载时,屏幕为空白。我们下载了,浏览器又开始了六个步骤。请耐心一点,我将比下载快一些。



让我们从解析开始。解析是指浏览器下载了字节流,然后开始将其分解为它可以理解的实体。



例如,他遇到了进口。必须再次下载。再次阅读报告的第一篇吗?导入是一项阻止操作。但是浏览器很聪明。他们有一个预载扫描仪。我说那里一切都被封锁了,这是不正确的。浏览器知道,例如,如果连续有三个遵循该样式的链接标记,那么当我下载第一个链接标记时,可以开始下载第二个和第三个链接标记。它无法解析,因为解析的整个结构都中断了。但是,请提前下载-可以。



因此导入是一件坏事。如果样式在HTML中是一致的,则浏览器将看到我们将进一步查找另一个文件。



如果直接将其插入导入,则应先下载style.css,然后在其中查看导入。他开始解析此CSS ...是的,我们以一种新的方式阻止了所有内容,并准备文件!因此,您可以在网站上进行非优化以创建一个很棒的瀑布。

忘记导入或配置,以便在构建后不进行任何导入。对于开发环境,还可以,但对用户而言不行。



接下来,我们使用Cascade进行树木构建的各个阶段。



所有这些也已经描述了很长时间。 CSS对象模型是建立的-浏览器如何将标签,类映射到样式的特殊树。他将所有内容链接到DOM,并很快建立了这些连接。当您更改某些内容时,他在树内更改它就足够了。



选择器越大,浏览器绘制树就越困难。他需要解析选择器,将其转换为树结构。如果您插入了!重要的是,那么他应该考虑到这一点。



似乎是时候再次讨论BEM。但是,如果您知道如何使用实用程序类,一个类负责一种功能并且它们不会互相干扰,则BEM并不是必需的。然后建造一棵树很简单。您的结构相当平坦,然后浏览器应将其正确链接到DOM。



如果这样做,他们会说这样的选择器会减慢CSS解析速度。但是这些都是很久以前的传说,对于浏览器来说差别很小,如果您使用星号优化选择器,则在普通项目中您不会注意到它。但是您想开发和维护这样的代码吗?



我曾经听过提示:尝试将所有内容都放在快捷方式中。背景是许多其他属性的快捷方式。我们将所有内容放在一个属性中,并且它变得最优。

以字节为单位,是的,它越来越小。但是,如果您想优化CSS OM的组成,那么浏览器仍然会将所有这些属性置于后台。每个DOM元素的浏览器都会建立一个表,其中包含它可以拥有的所有属性。当您查看DevTools计算值时,它们不存在,因为浏览器会根据您的要求进行计算。它将其存储在内存中,因为重写一个属性要容易得多,并且一切正常。

这也是非常奇怪的建议,但是如果您想使CSS OM更快,则可以立即一次设置所有属性。那可能行得通。但是捆绑包的大小将大大增加。您需要测量。我怀疑它会带来利润,但是突然之间!

构建CSS OM时,此时JS也被锁定。如果构建OM CSS需要两秒钟,则JS失败。尽管我无法想象您如何设法用CSS编写了这么多文件,但树却被建立了两秒钟。



浏览器进一步执行布局。这是所有DOM元素的位置,使用位置。他了解该元素应位于何处以及具有什么尺寸。在这个阶段,用户似乎应该已经看到了某种图片。但是他看到了视口中的所有内容,可以通过有限的窗口查看。如果下面有什么不对劲的地方,他根本看不到。



这个想法叫做Critical CSS,它也很古老。在下载开始时,请为第一个屏幕插入一些重要内容。例如,在您的HTML中内联,摆脱任何其他请求。用户首先看到此屏幕,然后根据需要下载。最有可能的是,当您有时间加载它时,他将开始滚动。



这很简单。有一些工具可以自动完成所有这些工作,包括用于webpack和React的插件。只需搜索并正确配置即可。

- github.com/addyosmani/critical
- github.com/pocketjoso/penthouse
- github.com/anthonygore/html-critical-webpack-plugin
- github.com/GoogleChromeLabs/critters



有一个好的方法来自Filament Group的-如何异步加载而不阻塞CSS。一切都很简单。

当您放置<link rel = preload>时,然后告诉浏览器:“我将需要这种样式,但现在我们不阻止任何内容。您现在下载它,缓存它,当我转向它时,就开始构建CSS OM。”然后,您只需要进行加载和处理即可,“好吧,因为我下载了它,所以执行rel = stylesheet,启用解析”。

一种相当简单的方法,但也要明智地使用它。如果您的预紧力太大,您可能会做得更糟。



您也可以使用媒体表达式。粘贴它们并告诉浏览器:“现在不需要此样式,但是当此媒体表达起作用时,将需要它。”浏览器也将主动下载,但优先级较低且没有阻止。



另一种疯狂的方法,但不是那么疯狂-当您具有http / 2推送时。您可以将CSS嵌入在块的前面。没有CSS,您的代码块看起来将不会很好。那么,为什么不内联此块之前的下一个块所需的CSS?这是合乎逻辑的,并且http / 2推送将使您对其进行优化。

一种简单的方法。如果展开它,请使用延迟加载。用户为什么要下载他不会使用的内容?您可以配置React组件,以便如果它从未出现在页面可见性区域中,那为什么还要为其自己下载样式呢?

探索Intersection Observer API,您也许可以大大加快页面的速度。



最后一步是绘制并应用于复合层,将其粘合等。



浏览器在很多情况下都会创建复合层。我认为,这里只有四分之一 Chromium 源代码适合您可以在浏览器代码中创建复合层时亲自查看。

显存有限,尤其是在手机上。如果将所有内容带到新的图层上以使用will-change:transform或其他方法优化动画,那么您的表现可能会更糟。

创建更少的层-完全与当前优化所需的层数相同。

太好了,我们都解析了。

如果我回来?


如果我返回页面怎么办?这只是我第一次去。

返回页面,我似乎可以立即下载所有内容。我已经下载了所有资源,为什么不第二次使用它们呢?



如果服务器未提供Cache-Control标头,则浏览器将尝试缓存您的文件以重新使用它。您可以默认配置服务器,例如:“将该文件缓存一整年”。不会改变。但是,如果是这样,则需要处理全局缓存失效问题。但这是另一份报告的主题。

使用服务人员!到了2020年,渐进式Web应用程序! Kirill Chugainov的报告不错关于如何在不同场合使用Service Workers。在这种情况下,您将拦截CSS请求并保存,如果浏览器第二次遵循此样式,则将其从缓存中释放。

但是浏览器不向您承诺任何内容。您总是可以面对这样的事实,浏览器的内存已用完。他将尝试缓存,但没有内存。缓存不是百分之一百。始终处理此类情况。

您可以尝试使用本地存储。但是他异常缓慢。有时下载文件比使用本地存储API更快。

您可以尝试使用内置的浏览器数据库。但是测量一下。由于处理器较弱,也许去JS旅行会花更长的时间。

您还可以提前告知浏览器您将下载一些内容。



<link rel>-了解此属性的工作方式。有预连接,预取和预渲染-我想分别谈一谈。他说:“我现在在此页面上,然后我将转到下一页。在背景标签中下载此页面的所有内容并绘制。”酷的东西。在任何地方都无法使用。



从某种意义上说,它在IE和Edge中都受支持。在Chrome中,它实际上并没有执行此操作,也不会渲染。就像预取一样工作:下载这些文件并缓存。不幸的是,全面的预渲染无法在任何地方使用。

但是您可以提出这个想法。例如,在Yandex应用程序中-自然地,不使用CSS-进行了预渲染。当您寻找某物时,您可能会立即获得结果。我们可以预测您的去向,并通过我们自己的方法预先获得所有必要的资源。

下一步是什么?有很多链接。我还建议您看一下Vanya Akulov所做的所有优化的惊人集合雅马库洛夫了解如何同时优化HTML,JS和程序集。

并且不要忘记整理。现在,我的建议确实有效,建议如何快速进行操作,但很可能在五年后甚至会变得有害。将会有某种与之不兼容的技术。跟踪此情况,并尝试使代码保持最佳状态,包括一段时间后。谢谢您的关注。

All Articles