测试环境:windows/chrome

实例1:页面中仅有图片

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<img src="1.jpg" width="200" height="300" />
</body>
</html>

1、上图中红色框框出来的蓝色的线就是DOMContentLoaded event的时间,而此时图片(1.jpg)还未加载,正好才Send Request(1.jpg)。由此可以看出DOMContentLoaded事件并没有等待图片加载完成。

2、图片1.jpg一加载完,就立刻解码了(Image Decode)。

实例2:页面中有css和图片

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<img src="1.jpg" width="200" height="300" />
</body>
</html>

从上图中可以看出:

1、DOMContentLoaded事件不直接等待CSS文件和图片的加载完成。

2、CSS阻塞了图片的解码。可以从图片加载好之后有Recalculate Style和Layout,理论上也可以理解,因为CSS中可能对图片进行了样式上的修改之类的。所以要等到CSS加载和执行完才知道。

实例3:页面中有JS、CSS和图片

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script type="text/javascript" src="jquery1.js"></script>
<link href="style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="jquery2.js"></script>
</head>
<body>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<img src="1.jpg" width="200" height="300" />
<script type="text/javascript" src="jquery3.js"></script>
</body>
</html>

jquery1.js

console.timeStamp('Inline script before link in head');
//console.timeStamp() 可以向Timeline中添加一条记录,并对应上方的一条黄线。

jquery2.js

console.log('test');

从上图可以看出:

1、DOMContentLoaded事件要等到所有JS执行完才触发。

2、在CSS之前的jquery1.js一加载完了就立刻执行。而在CSS后的JS需要在CSS加载完之后才执行,比如说jquery3.js很早就加载完了,但是它等到style.css加载完了之后才执行,而且它还是在jquery2.js执行了之后才执行的,这是由于jquery3.js放在了jquery2.js之后。虽然对于现代浏览器,这些CSS、JS资源是并发请求的(从Send Request可以看出)。

总结:现代浏览器会并发的预加载CSS, JS,也就是一开始就并发的请求这些资源,但是,执行CSS和JS的顺序还是按原来的依赖顺序(JS的执行要等待位于其前面的CSS和JS加载、执行完)。先加载完成的资源,如果其依赖还没加载、执行完,就只能等着。

实例4:只有JS和图片

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script type="text/javascript" src="jquery.js"></script>
</head>
<body>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<img src="1.jpg" width="200" height="300" />
<script type="text/javascript" src="jqueryE.js"></script>
</body>
</html>

其中jquery.js很大,有900+KB。jqueryE.js更大,1.8MB。目的就是为了测试两个JS是否会阻塞图片的解码。

从上图可以看出,jquery.js加载并执行了之后,才进行图片解码的(即使图片在很早之前就加载完成了),而jqueryE.js是在图片解码之后才执行的。说明<head>标签里的script会阻塞图片的展现。而放在<body>最下面的JS则不会。

为了进一步验证<head>标签里的script会阻塞图片的展现,我把jquery.js修改了下,改的更加大,结果还是一样,图片在JS执行了之后才解码的。

此外我还测试了,如果jqueryE.js比较小的话,它还是会在图片解码前加载并执行完成的,所以说,讨论了这么多,在实际应用中,还是要具体情况具体分析!而且chrome在这方面也一直在不断的更新优化。这个探讨可以说只是一个参考,让大家有这么一个思想,关键是要结合自己的业务、需求场景,有针对性的做分析和优化。

接下来,我们尝试几种优化方法来看看实际结果如何:

1、使用async  (我们仍然使用实例4中的代码例子,区别只是加了async属性)

async:这个是html5中新增的属性,它的作用是能够异步的加载和执行脚本,不因为加载脚本而阻塞页面的加载。一旦加载到就会立刻执行。需要注意的是async属性仅适用于外部脚本(只有在使用 src 属性时)。

在有async的情况下,js一旦下载好了就会执行,同时会在window的load事件之前执行。所以很有可能不是按照原本的顺序来执行的。如果js前后有依赖性,用async,就会有可能出错。

除此之外我还发现,原来DOMContentLoaded事件要等到JS执行完才触发,但如果设置了async,就不会等了。图片也加载完了之后就解析了,不会去等脚本。

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script type="text/javascript" src="jquery.js" async></script>
</head>
<body>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<img src="1.jpg" width="200" height="300" />
<script type="text/javascript" src="jqueryE.js" async></script>
</body>
</html>

FF:

上面这张图片中看出了一个问题,jquery.js的加载共用了101ms,GET1.jpg被阻挡了101ms,和GET jqueryE.js同步。这点和chrome有很大的区别(对比chrome的network图就可以看出)。这应该是浏览器内部机制不同导致的。所以说,尽量不要把脚本放在<head>里面。

2、使用defer

defer属性规定是否对脚本执行进行延迟,直到页面加载为止。它将推迟对脚本的解释,直到文档已经显示给用户为止。

对于带有defer的script,它们会确保按在页面中出现的顺序来执行,它们执行的时机是在页面解析完后,但在DOMContentLoaded事件之前(chrome中测试如此,但是在firefox中,defer脚本会在DOMContentLoaded之后执行)。

对于defer,我们可以认为是将外链的js放在了页面底部。js的加载不会阻塞页面的渲染和资源的加载。不过defer会按照原本的js的顺序执行,所以如果前后有依赖关系的js可以放心使用。

FF:可以看出脚本是在DOMContentLoaded(蓝线)之后执行

对于defer和async两个属性特别需要注意的是:1、对于inline的script无效。2、使用这两个属性的脚本中不能调用document.write方法。

浏览器兼容:

Javascript、CSS和IMG之网页执行探索的更多相关文章

  1. 利用插件对某些网页执行javascript代码

    说明 javascript在浏览器地址栏中可以运行,也可以按F12在控制台中运行,还可以写一个插件让javascript针对某些网页执行,可以使用chrome浏览器的Content scripts,C ...

  2. javascript怎么获取指定url网页中的内容

    javascript怎么获取指定url网页中的内容 一.总结 一句话总结:推荐jquery中ajax,简单方便. 1.js能跨域操作么? javascript出于安全机制不允许跨域操作的. 二.用ph ...

  3. 网页绘制图表 Google Charts with JavaScript #2 ....与ASP.NET网页结合 (ClientScriptManager.RegisterStartupScript 方法)

    此为文章备份,原文出处(我的网站) 网页绘制图表 Google Charts with JavaScript #2 ....与ASP.NET网页结合 (ClientScriptManager.Regi ...

  4. Spring Mvc + Maven + yuicompressor 使用 profile 来压缩 javascript ,css 文件; (十)

    profile相关知识点: 在开发项目时,设想有以下场景: 你的Maven项目存放在一个远程代码库中(比如github),该项目需要访问数据库,你有两台电脑,一台是Linux,一台是Mac OS X, ...

  5. javascript/css压缩工具---yuicompressor使用方法

    1. 下载 地址:https://github.com/yui/yuicompressor/downloads 2. 安装 yuicompressor是由java写成的一组jar文件,需要jdk环境支 ...

  6. Javascript位置 body之前、后执行顺序

    简介:当页面加载的时候,嵌入html标记的js代码和位于<body></body>之间的js代码将被执行:当调用的时候,位于<head></head>之 ...

  7. 引用CSS文件到html网页里方法

        引用CSS文件到Html方法-css引入,css引用 使用不同的方法来引用css样式表,最终到达的效果相同,但是使用不同方法应用的css文件将影响到SEO及网页打开速度效率. html引用cs ...

  8. JavaScript CSS Style属性对照表

    JavaScript CSS Style属性对照表 盒子标签和属性对照 CSS语法 (不区分大小写) JavaScript语法 (区分大小写) border border border-bottom ...

  9. 有人说,即使没有JavaScript,你也可以做网页。在纯HTML

    有人说,即使没有JavaScript,你也可以做网页.在纯HTML +服务器端语言理论中也可以完成所有功能,那么,为什么以及在哪里存在JavaScript?   JS,全称JavaScript   在 ...

随机推荐

  1. 简单的例子 关于Java内存管理的讲解

    我想做的是,逐行读取文件,然后用该行的电影名去获取电影信息.因为源文件较大,readlines()不能完全读取所有电影名,所以我们逐行读取. 就这段代码,我想要在位置二处使用base64,然后结果呢? ...

  2. WinForm 窗体基本属性、公共控件

    一.WinForm:客户端程序制作 - C/S (B/S:服务器端) 它是基于.NET Framework框架上运行,不是必须在windows系统上才能运行---------------------- ...

  3. phpize建立php扩展 Cannot find config.m4

    centos  php  安装 memcache 扩展的时候   爆 Cannot find config.m4 错误 解决方案参考以下文章 参考文章 http://blog.csdn.net/wgl ...

  4. sql2008r2数据库附加的问题

    sql2008r2数据库附加,一般都没有问题,但是偶尔也会出错,无法附加,一般的原因都是权限不够,主要是:Authenticated Users要开通完全控制功能,选中该用户(如果没有该用户,就添加) ...

  5. Java期末设计(十三周)

    一.项目完成计划     十三周和十四周完成用户交互界面的设计(1.登陆界面2.订票以及查询界面3.用户管理界面4.退票界面):     十三周完成登陆界面,十四周完成订票以及查询界面,用户管理界面和 ...

  6. 开启Win7系统管理员Administrator账户

    Win7系统凭借酷炫的界面以及简单.易用.快速.安全等特点,迅速成为全球最受用户喜爱的操作系统,如今Win7已经成为身边很多朋友生活学习工作的好伙伴.在我们使用Win7的时候,有一些软件的正常运行需要 ...

  7. RHEL6.6 PXE安装-基于VMWare WorkStation

    ///////////第一部分:安装安装服务器 1.先安装一台RHEL6.6的服务器A(地址为192.168.139.132),作为安装服务器.这样后面的机器就可以指向这台服务器进行自动安装 2.在A ...

  8. 分析自定义view的实现过程-实现雪花飞舞效果(转载有改动)

    声明:本文源码出自实现雪花飞舞效果(有改动)主要通过这篇文来分析自定义view的实现过程. 没事时,比较喜欢上网看看一些新的东西,泡在网上的日子就是一个很不错的网站. 下面开始了,哈哈.^_^ 大家都 ...

  9. C++多线程1

    一个多线程的实例 #include "stdafx.h" #include <windows.h> DWORD __stdcall Func(LPVOID pm) { ...

  10. AmazeUI定制

    定制流程 下载 Amaze UI 源码:从 GitHub 选择版本,点击 Source code (zip) 下载并解压(定制只适用于 Amaze UI 2.x): 下载安装 Node.js: 全局安 ...