布置行内脚本

一.避免行内脚本阻塞渲染

  • 把行内脚本移至底部(body结束标签前)

  • 使用异步回调启动JavaScript的执行

  • 使用script的defer属性

把行内脚本移至底部

把行内脚本放在body的结束标签前

优点:简单易用,页面内的图片等资源和位于底部的行内脚本并行下载

缺点:仍然会阻塞页面渲染,如果行内脚本执行时间很长(大于300ms),就不应该用这种简单方法了

异步启动执行脚本

通过setTimeout(doStuff, 0)来异步执行脚本,在Firefox中需要延迟250ms(250是Nglayout.initialpaint.delay

优点:可以实现逐步渲染,在行内脚本开始执行之前,浏览器会先渲染DOM内容(多半是文字)

缺点:会阻塞图片的渲染,如果图片响应返回时正在doStuff,图片将等到doStuff结束才会显示。此时应该放弃setTimeout,改用window.onload启动脚本执行。当然,如果行内脚本执行时间很短(小于300ms),用setTimeout是没问题的

P.S.对于执行时间很长的行内脚本,最理想的方案是每隔300ms分块执行,setTimeout(doChunk, 300),但需要大规模重构代码,把大块逻辑分成一些小片段(300ms内能够完成的)

使用script的defer属性

defer属性也适用于行内脚本,允许浏览器继续解析和渲染页面的同时延迟执行行内脚本

优点:资源并行下载

缺点:阻塞渲染,只适用于执行时间较短的行内脚本,很长的脚本仍然需要setTimeout

二.样式表也会阻塞行内脚本

除了按引入顺序执行js,浏览器还会保证按引入顺序解析css(因为不同的解析顺序会导致不同的样式结果,比如同优先级样式覆盖规则)

鲜为人知的:浏览器还会保持css和js的解析顺序,如果把行内脚本放在样式表之后,会明显地延迟资源的下载(结果是样式表下载完成并且行内脚本执行完毕时,后续资源才能开始下载)

这是因为行内脚本可能含有依赖于样式表中样式的代码,比如document.getElementsByClassName()

结论:在样式表后面的行内脚本会阻塞所有后续资源的下载(或者说,如果样式表后面没有行内脚本的话,样式表将与其它资源并行下载。当然,无论行内脚本前面有没有样式表,行内脚本都会阻塞后续资源的下载)

三.总结

行内脚本可能会导致css变成阻塞的,保证只引用外部脚本就可以避免这个问题

参考资料

  • 《高性能网站建设进阶指南》

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

code