JS和CSS执行顺序

15 篇文章 6 订阅

一、脚本和样式表加载、执行顺序总结

1、脚本

web的模式是同步的,开发者希望解析到一个script标签时立即解析执行脚本,并阻塞文档的解析直到脚本执行完。如果脚本是外引的,则网络必须先请求到这个资源——这个过程也是同步的,会阻塞文档的解析直到资源被请求到。这个模式保持了很多年,并且在html4及html5中都特别指定了。开发者可以将脚本标识为defer,以使其不阻塞文档解析,并在文档解析结束后执行。Html5增加了标记脚本为异步的选项,以使脚本的解析执行使用另一个线程。

2、样式表(Style sheets)

样式表采用另一种不同的模式。理论上,既然样式表不改变Dom树,也就没有必要停下文档的解析等待它们,然而,存在一个问题,脚本可能在文档的解析过程中请求样式信息,如果样式还没有加载和解析,脚本将得到错误的值,显然这将会导致很多问题,这看起来是个边缘情况,但确实很常见。Firefox在存在样式表还在加载和解析时阻塞所有的脚本,而Chrome只在当脚本试图访问某些可能被未加载的样式表所影响的特定的样式属性时才阻塞这些脚本。

3、预解析(Speculative parsing)和prefetch 优化
Webkit和Firefox都做了这个优化,当执行脚本时,另一个线程解析剩下的文档,并加载后面需要通过网络加载的资源。这种方式可以使资源并行加载从而使整体速度更快。需要注意的是,预解析并不改变Dom树,它将这个工作留给主解析过程,自己只解析外部资源的引用,比如外部脚本、样式表及图片。

因此,可能你会看到在后面的脚本先下载,在前面的脚本才执行。

(个人对预解析和prefetch优化理解:预先解析<script>、<link>等标签,预先加载这些资源。但请求到的内容之后不会去具体执行)。

来看个预解析的实例:

上面代码在的网络请求如下图,有一个点:mod_36ad799.js等几个js为什么会在hm.js之前下载?

按照“脚本会阻塞文档执行,直到脚本完成下载并执行“理论来看,应该是等hm.js下载完成后才下载后面的js。

但现代浏览器有预解析机制,因此会预先加载js资源,但js执行会按照顺序来执行。因此其他mod_36ad799.js会先下载,hm.js是要等到执行js时才去加载。




4、加载顺序原因分析:

JS 和 CSS 在页面中的位置,会影响其他资源(指 img 等非 js 和 css 资源)的加载顺序,究其原因,有三个值得注意的点:

JS 有可能会修改 DOM。典型的,可能会有 document.write.。这意味着,在当前 JS 加载和执行完成前,后续所有资源的下载有可能是没必要的。这是 JS 阻塞后续资源下载的根本原因。

JS 的执行有可能依赖最新样式。比如,可能会有 var width = $('#id').width(). 这意味着,JS 代码在执行前,浏览器必须保证在此 JS 之前的所有 css(无论外链还是内嵌)都已下载和解析完成。这是 CSS 阻塞后续 JS 执行的根本原因。

现代浏览器很聪明,会进行预解析(Speculative parsing)和prefetch 优化 。这意味着,在不存在任何阻塞的情况下,理论上 JS 和 CSS 的下载时机都非常优先,和位置无关。但是不会执行<script>的内容,包括绑定的事件。

四、脚本和样式表放置位置建议

首页的样式表放在<head>标签中,可以避免IE出现FOUC(无样式闪烁,刚开始没有样式,后来获取到样式文件,突然有样式)。

脚本尽量放在<body>标签最后面,可以减少白屏时间,加快首屏出现速度。

五、<script>和<link>的onload触发顺序

onload不是在文件下载完后触发,而是在执行完js文件或者解析完css文件时触发。

<script>一定比它前面的<script>晚触发onload。<link>不一定比它前面的<link>晚触发onload,后出现的<script>也不一定会比前面的<link>晚触发,这跟文件大小等因素是有关系的。

jquery-1.9.0.js和bootstrap.min.css比较大。而test.js和test.css很小。

<link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css" οnlοad='console.log("1")'/>  
<link rel="stylesheet" href="test.css" οnlοad='console.log("2")'/>
<script src="https://code.jquery.com/jquery-1.9.0.js" οnlοad='console.log("3")'></script> 
<script src="test.js" οnlοad='console.log("4")'></script> 
test.js:
console.log('hi');
test.css:
.body {font-size:12px;background-color:pink;}
打印结果是:2-->1-->3-->4


六、参考链接:

1、前端性能:http://www.cnblogs.com/chuaWeb/p/PerformanceMonitoring.html。主要参考这篇文章写的

2、网站前端性能优化之javascript和css:http://www.haorooms.com/post/web_xnyh_jscss。这篇文章写得很完善,推荐阅读

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值