我们先研究下构建渲染树前的几个步骤:也就是DOM和CSSOM,通常这些步骤的效果最差使你的网页呈现速度非常慢,我们是讨论尽可能快的将HTML流式传输给客户端,使浏览器能够开始构建DOM,还有其他注意事项吗?有一个HTML的尺寸呢?我想应该尽可能小,我们来看看实现这一目的一些策略,假设我想要优化这个HTML
要优化CSSOM,我们需要删除不必要的样式,缩小和压缩文件并缓存,对吧?对,这些都是很好的策略,安市没记错的话,当我们运行PageSpeed Insignts的时候,它还推荐我们查看下阻止呈现的CSS。假设有个简单的网页,包含一个CSS文件,浏览器下载了HTML然后发现并获取CSS,浏览器最早什么时候就会绘制网页?
我们不能绘制没有样式的网页,也就是阻止呈现的CSS,可以对此作出优化?CSS使我们能够按照特定条件范围应用样式,如这个文件,body规则在所有条件下都适用。但是当设备处于横向模式时,我们会应用特殊的规则。是菜单悬浮在右侧,类似的,如果有用户想要打印网页,我们就会调整文本大小,适用更小的字号,媒体查询对自适应设计来说很重要,但是这回如何帮助我优化关键渲染路径呢?假设我要呈现使用这个CSS文件的网页,我们注意到浏览器会阻止呈现,直到解析了所有的样式,但是直观的来说,你认为它应该对print规则阻止呈现吗?我认为如果我们不打印网页的话,则没必要呈现,对吧?对,这就是为何有时候需要将CSS拆分成多个文件,我们来试试。
接着想HTML标记中再添加一个链接,现在是重点内容了,默认情况下,浏览器会认为每个具体样式表都会阻止呈现,但是我们也可以通过在媒体查新中添加媒体属性来告诉浏览器何时应该应用样式表,style-print仅用于打印,所以我们添加media=“print”,所以当浏览器看到这个样式表就知道仅需要应用到打印操作中,因此当我们在手机上加载时则不需要阻止呈现,对,浏览器依然会下载这个两个样式表,但是不会对style-print.css阻止呈现。这里就意味着,浏览器会为style.css下载更少的数据,从而加快了下载速度,有道理,但是这个示例很简单,假设有一组更加复杂的样式,包括多个断点,这一技巧还有用?完全有用,你可以在链接属性上指定任何媒体查询,浏览器将执行正确的操作。PageSpeed Insights建议减少关键CSS元素数量,现在看起来更加合理了。
如果我在手机上纵向地呈现网页,一下哪个样式会阻止呈现?默认情况下,浏览器会认为css在阻止呈现,因此第一个链接标记将阻止呈现,screen查询将为true,因为我要在屏幕上呈现内容,所以它会阻止呈现,第三项声明取决于设备的屏幕方面,这里因为设备方向是纵向,所以它不会阻止呈现资源。
现在我认为我明白如何优化HTML和CSS了,现在要优化渲染树了吗?快了,但是还没有谈论JavaScript,很明显是个重要的步骤,我们来看看,我来猜猜,缩小文件,压缩文件然后缓存?嗯这些都是不错的策略,但是对于JavaScript,你可能还看到PageSpeed Insights指出解析器屏蔽了脚本,我们来看看这是什么意思?如何优化,这里扩展了Hello world页面。
在底部添加了简单的脚本,我们逐步讲解下,首先,我们进入DOM并寻找第一个span元素,可以看出,其中包含“web performance”文本,接着我们对该DOM元素作出修改,更改其innerText,同事更改css属性,似乎很简单,是的,表明JavaScript可以同时操作DOM和CSS对象模型,它是个非常强大的工具,接着创建了新的div元素,设置了文本内容,css颜色属性并附加到网页上,我们在手机上加载下该页面,显示了我们修改的内容。这里可以采取什么措施来优化性能呢?有,优化JavaScript可以花费这个一门课程。
很强大,但是这会如何影响性能呢?请注意我们经历的步骤,当我遇到标记时,我们必须暂停DOM构建过程,让js先运行,然后才能继续js,会阻断解析,因为当我们遇到标记时,它会阻止DOM进行构建,明白了,但是影响不大吧?js速度很快,对吧?是的,但是我稍加修改下,
而是将脚本内容放入外部文件里,你觉得现在回发生什么情况?
获取文件并执行,哦,我明白了,获取文件可能要话费一段时间,对吧?当浏览器在获取该文件时遭遇到阻止,无法继续构建DOM,进而降低了关键选路径的速度
是的,标记阻止解析器继续操作,我一直等待获取该文件,效果不太好,如果外部js始终会阻止解析,似乎我应该内联所有的js,不完全对,内联js会减少请求次数,但是也有一些缺点,如果你在多个网页上使用相同的代码,那么这些网页就会出现多余的代码,所以需要权衡。对于特定于一个网页的代码来说,似乎是个不错的策略,是这样的,但是我们来看看相关的利弊和陷阱。
思考下这段代码会发生什么情况,我们进入文档找到所有的段落标记,并对第一个的CSS颜色样式设为红色,样式表规定所有段落文本都应该呈现为黑色,如果在脚本已经执行并将颜色设置为红色后才获得了css样式表,会怎样?浏览器会知道会使用哪个颜色吗?会,下面这个简单图表描绘了实际上发生的情况,浏览器请求HTML一旦获得响应,就开始构建DOM然后发现CSS并发出请求,然后解析器继续操作并找到标记,此时就需要阻止了。它不知道脚本将执行什么操作,因为脚本可能会尝试访问CSS属性,所以它会阻止脚本执行,直到获得CSS并构建CSS对象模型。然后我们才会运行js并完成DOM构建过程。
再次表明优化css非常重要。
内联脚本会被CSS阻止,所以让CSS速度更快的策略都有帮助,实际上为何不内联CSS呢?嗯,这样会减掉一次请求步骤,肯定有帮助,那么js本身呢?你认为它应该阻止呈现?我认为不应该,它向某个分析服务器报告了访问数据,没必要阻止呈现,对吧!
你刚刚提到了个重要发现,某些脚本不修改DOM或CSSOM,不应该阻止呈现,分析工具就是一个很好的例子,真希望能有某种方式告诉浏览器这一点。实际上,是可以的,一种策略是在网页加载后再加载脚本,当浏览器发出onload事件时,再去执行脚本。怎么做呢?当网页加载完毕后,浏览器就会发出onload事件,你可以等待该事件,然后执行脚本。还有个更简单的办法,就是在标记中添加一个属性。