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

  1. JS 有可能会修改 DOM. 典型的,可能会有 document.write. 这意味着,在当前 JS 加载和执行完成前,后续所有资源的下载有可能是没必要的。这是 JS 阻塞后续资源下载的根本原因。
  2. JS 的执行有可能依赖最新样式。比如,可能会有 var width = $('#id').width(). 这意味着,JS 代码在执行前,浏览器必须保证在此 JS 之前的所有 css(无论外链还是内嵌)都已下载和解析完成。这是 CSS 阻塞后续 JS 执行的根本原因。
  3. 现代浏览器很聪明,会进行 prefetch 优化。性能是如此重要,现代浏览器在竞争中,在 UI update 线程之外,还会开启另一个线程,对后续 JS 和 CSS 提前下载(注意,仅提前下载,并不执行)。有了 prefetch 优化,这意味着,在不存在任何阻塞的情况下,理论上 JS 和 CSS 的下载时机都非常优先,和位置无关。

以上三点可简述为三条基本定律:

  • 定律一:资源是否下载依赖 JS 执行结果。
  • 定律二:JS 执行依赖 CSS 最新渲染。
  • 定律三:现代浏览器存在 prefetch 优化。

有了这三条定律,再来看克军的测试,就很清晰了:

a,b – head里出现外联js,无论如何放,css文件都不能和body里的请求并行

根据定律一和定律三,可以知道上面的结论不够正确。比如:

1 <head>
2 <link rel="stylesheet" href="mock.php?css1&sleep=2">
3 <script src="mock.php?js&sleep=3"></script>
4 <link rel="stylesheet" href="mock.php?css2&sleep=4">
5 </head>
6 <body>
7 <link rel="stylesheet" href="mock.php?css3&sleep=5">
8 <img src="test.gif">
9 </body>

在 Chrome 下的瀑布图是:

黄色条是 js 的,可以看出 img 的延时下载是由定律一决定的。

定律三则决定了所有 js/css 都是并行开始下载的。在 Firefox 10 下,prefetch 非常强悍,对 img 也会预加载,瀑布图如下:

调整一下 sleep 时间,还可以观察到定律二的威力:

1 <head>
2 <link rel="stylesheet" href="mock.php?css1&sleep=3"> <!-- 修改 sleep 值,使其大于 js 的 -->
3 <script src="mock.php?js&sleep=2"></script>
4 <link rel="stylesheet" href="mock.php?css2&sleep=4">
5 </head>
6 <body>
7 <link rel="stylesheet" href="mock.php?css3&sleep=5">
8 <img src="test.gif">
9 </body>

瀑布图立刻发生了变化:

因为定律一,决定 img 的下载在 js 执行后。又因为定律二,决定 js 的执行在第一个 css 后。于是最后在瀑布图上体现出来,就是 img 的下载在第一个 css 后。

再来看克军的第二个结论:

c – head里的内联js只要在所有外联css前面,css文件可以和body里的请求并行(图2)
d – head里的内联js只要在任一外联css后面,css文件就不能和body里的请求并行(图1)

这个是定律二的威力。结论 c 是正确的,因为没有 css 会影响 js 的执行。结论 d 则不够正确。img 等其他资源,会在 js 前面的 css 下载完成后,以及 js 执行后,立刻开始下载。与头部中,js 位置之后的 css 没关系。

克军的其他结论都是对的,不多说。

注意1:Firefox 10 的 prefetch 有点奇怪,有时会对 img 进行 prefetch,有时则不会。有兴趣的可以进一步寻找规律。
注意2:上面的三个定律,是黑盒猜测,有兴趣的可以去阅读浏览器的源码,应该能找到更深层次的原因。
注意3:本文没有考虑 defer, async 属性的影响,这是另一个故事。

浏览器在迅速发展,很多总结,特别是书籍上的,很难与时俱进。大家应该像克军学习,多测试,多发现,这样得来的知识,才不会过时。这篇博客的总结,也肯定在未来甚至就在现在,已经存在错误。这些都无所谓,关键是要懂得测试的方法和分析的思路,有了“渔”,才能更好地探求和拥有“鱼”

JS 和 CSS 的位置对其他资源加载顺序的影响的更多相关文章

  1. SpringBoot——配置文件加载位置及外部配置加载顺序

    声明 本文部分转自:SpringBoot配置文件加载位置与优先级 正文 1. 项目内部配置文件 spring boot 启动会扫描以下位置的application.properties或者applic ...

  2. java类中资源加载顺序

    根据优先级别从高到低依次为:1.父类中的静态代码块(static);2.自身的静态代码块;3.父类中的的普通代码块;4.父类的构造方法;5.自身的普通代码块;6.自身的构造方法; 下面是一个测试 结果 ...

  3. Cocos Creator 资源加载流程剖析【一】——cc.loader与加载管线

    这系列文章会对Cocos Creator的资源加载和管理进行深入的剖析.主要包含以下内容: cc.loader与加载管线 Download部分 Load部分 额外流程(MD5 Pipe) 从编辑器到运 ...

  4. 关于html,css,js三者的加载顺序问题

    <head lang="en"> <meta charset="utf-8"> <title></title> ...

  5. CSS样式表、JS脚本加载顺序与SpringMVC在URL路径中传参数与SpringMVC 拦截器

    CSS样式表和JS脚本加载顺序 Css样式表文件要在<head>中先加载,这样网页显示时可以第一次就渲染出正确的布局和样式,网页就不会闪烁,或跳变 JS脚本尽可能放在<body> ...

  6. 打开一个网站,加载顺序是什么?先加载HTML然后JS然后CSS?还是什么?

    HTML页面加载和解析流程 : 1. 用户输入网址(假设是个html页面,并且是第一次访问),浏览器向服务器发出请求,服务器返回html文件. 2. 浏览器开始载入html代码,发现<head& ...

  7. js写css()方法,记得加引号“ ”,除非是数字

    js写css()方法,记得加引号“ ”,除非是数字.如: $("#android").css({ "position": "absolute" ...

  8. 性能优化之html、css、js三者的加载顺序

    前言 我们知道一个页面通常由,html,css,js三部分组成,一般我们会把css文件放在head头部加载,而js文件则放在页面的最底部加载,想要知道为什么大家都会不约而同的按照这个标准进行构建页面, ...

  9. 再谈DOMContentLoaded与渲染阻塞—分析html页面事件与资源加载

    浏览器的多线程中,有的线程负责加载资源,有的线程负责执行脚本,有的线程负责渲染界面,有的线程负责轮询.监听用户事件. 这些线程,根据浏览器自身特点以及web标准等等,有的会被浏览器特意的阻塞.两个很明 ...

随机推荐

  1. C语言sizeof

    一.关于sizeof 1.它是C的关键字.是一个运算符,不是函数: 2.一般用法为sizeof 变量或sizeof(数据类型):后边这种写法会让人误认为是函数,但这种写法是为了防止和C中类型修饰符(s ...

  2. JAVA 数组实例-求学生成绩的最大成绩,获取数组中的最大值、最小值

    实例: import java.util.*; //求学生最大成绩 public class Test{ public static void main(String[] args){ System. ...

  3. JAVA变量的类型,定义变量

    JAVA中常用的数据类型 数据类型 数据类型解释 说明 char 字符型 用于存储单个字符,如:性别“男”.“女”,电灯“开”.“关” int 整形 用于存储整数,如一天的时间是24小时,一月份是31 ...

  4. js中如何操作json数据

    一.要想熟练的操作json数据,就先要了解json数据的结构,json有两种结构:对象和数组. 1.对象 一个对象以“{”开始,“}”结束.每个“名称”后跟一个“:”:“‘名称/值’ 对”之间使用“, ...

  5. linux 交换分区分配规则

    一般地, 内存小于2G ,则swap=2*RAM, 内存大于2G, 则swap=2+RAM, 然后满足上述规则就行.

  6. Dubbo的Maven打包

    Maven项目的依赖,我们可以通过下面命令看到,打包时,会按照这个依赖编译进去对应模块. 参考:http://www.cnblogs.com/ghj1976/p/5336923.html mvn de ...

  7. nyoj 95 众数问题

    点击打开链接 众数问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 所谓众数,就是对于给定的含有N个元素的多重集合,每个元素在S中出现次数最多的成为该元素的重数, 多 ...

  8. (整理)C#实现UDP广播

    (一) IP地址解析 IP地址的类型:XXX.XXX.XXX.XXXA类: 1.0.0.1--126.255.255.254 最高位是0: 1个字节的网络地址和3个地址的主机地址 测试地址:127.X ...

  9. Android Studio 修改 包名 package name

    我们的包名中含有Nav,造成声音不能正常出来:需要改包名,但 android studio 改包名原来还是比较麻烦的,不过现在简单多了: 第一步,直接打开 AndroidManifast.xml 文件 ...

  10. 问题:glGenBuffers()函数没有定义怎么办

    链接glew.lib库,#include <gl/glew.h>. glew是opengl 的扩展库