CSSOM节点的创建就像DOM节点一样,稍后它们将被组合起来,但现在它们是下面这个样子。
CSSOM的构造阻塞了页面的渲染,所以我们希望在渲染树中尽早地加载样式,使它们尽可能轻巧,并在有效的时候延迟加载。
CSS优化策略使用媒体属性(@media)。
媒体属性指定加载样式需要满足的环境,例如,是否有最大或最小分辨率?是屏幕阅读器吗?
台式机非常强大,但移动设备不是,所以我们想要给他们最轻的有效载荷。我们可以假设一开始的时候只提供移动样式,然后将台式机上的样式放在媒体属性里,这样做不会阻止下载针对台式的机样式,但这些样式不会阻塞我们移动端页面的加载或耗尽移动端浏览器宝贵的资源。
延迟加载CSS
如果你有样式,可以等到第一个有意义的绘制之后再加载和计算,例如,在首屏看不到的内容,或者在页面响应之前不需要的内容。在添加样式之前,你可以利用脚本等到页面需要的时候再加载这部分样式。
这是如何实现的一个例子(),另一个例子()。
较少的选择器
将更多的元素链接在一起存在一个明显的缺点,即将会有更多的数据需要传输,从而扩大了CSS文件,另一方面,更多的选择器也会使客户端计算样式时消耗大量计算。
只提供你需要的
如果你作为前端工作了一段时间,就会知道CSS中的一个大问题是删除内容时的不可预测性。它设计时就被诅咒会不断增大。
要尽可能地精简CSS,请使用诸如uncss之类的工具web浏览器停止运行此脚本,或者可以寻找类似的网站,有很多类似的选择。
第三步 - JavaScript
然后,浏览器会在找到任何JavaScript节点时继续构建DOM / CSSOM节点,即找到外部或内联脚本。
因为我们的脚本可能需要访问或操作前面的HTML或样式,所以我们必须等到二者全部构建完成。
因此浏览器必须停止解析节点,先完成CSSOM构建,执行脚本,然后继续解析。这就是为什么人们会说JavaScript“阻塞解析”。
浏览器有一个称为“预加载扫描器”的东西,它将扫描DOM脚本并开始预加载它们,但脚本只有在构建了先前的CSS节点之后才顺次执行。
如果这是我们的脚本:
那么这将对我们的DOM和CSSOM造成如下影响:
JavaScript优化策略
优化脚本是我们可做的最重要的事情之一,也是大多数网站做得最糟糕的事情之一。
异步加载脚本
通过在我们的脚本上使用一个异步属性(async),可以告诉浏览器先不管这个脚本,以较低的优先级在另一个线程下载它,不要阻塞页面其余部分加载。一旦完成下载,这个脚本将被执行。
这意味着该脚本可能在任意时间执行,这会导致两个明显的问题。首先,它可能在页面加载之后执行很久,所以如果我们依靠它为用户体验做一些事情,那么我们可能会给我们的用户一个不太好的体验。其次,如果它在页面加载完成之前执行,我们无法预测它是否能够访问正确的DOM / CSSOM元素并可能会中断执行。
async属性对于不影响我们的DOM或CSSOM的脚本是非常好的,对不需要我们的代码内容的外部脚本也是非常好,对于其他影响用户体验的脚本来说不是必需的,例如分析或跟踪。但是如果你发现任何合适的场景,请使用它。
延迟加载脚本
defer属性非常类似于async属性,它也不会阻止我们的页面的加载,但是,它会等到我们的HTML解析完成后再顺次执行。
这对于将对我们的渲染树上起作用的脚本来说是一个非常好的选择,但是对于加载首屏内容,或者先前的脚本运行完成后再执行的情况并不重要。
这是使用延迟策略的另一个非常好的选择(),也可以使用类似addEventListener这样的东西。如果你想知道更多,那么这是一个开始阅读的好地方()。