js、css的阻塞问题
js、css的阻塞问题
这篇文章主要是探索js、css的加载顺序及其影响问题。
下面的代码可以让浏览器阻塞:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>阻塞代码</title>
</head>
<body>
<script>
// 阻塞代码,参数单位s
function blocking(blockingTime) {
function getTime() {
return new Date().getTime();
}
var startTime = getTime();
// getTime()得到的时间单位是ms,所以乘1000
while (getTime() < startTime + blockingTime*);
}
blocking();
</script>
<h3>hello</h3>
</body>
</html>
测试一:
<!DOCTYPE html>
<html> <head>
<meta charset="utf-8">
<title>JS/css</title>
<script>var start = +new Date;</script>
<script>
var end = +new Date;
console.log(end-start);
</script>
<link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">
</head> <body>
</body> </html>
注:其中的+为单目运算符,可以将对象转化为数字。
显然,在控制台输出的结果为0。因为上面的js语句刚刚执行完,就执行下面的语句,所以时间间隔几乎为0。
测试二:
<!DOCTYPE html>
<html> <head>
<meta charset="utf-8">
<title>JS/css</title>
<script>var start = +new Date;</script>
<link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">
<script>
var end = +new Date;
console.log(end-start);
</script>
</head> <body>
</body> </html>
这个测试中,我将css置于两个script之间,最后的输出结果为2870, 当然这个值是个随机数,一定是远远大于0的。
然后我们在打开开发者工具的Network的情况下点击刷新,这时再看console控制台打印出的值为2967, 然后我们观察加载css所需的时间:

2.97s,也就是2967ms。
结论: 外部样式的加载会阻塞在它之后的<script>语句的加载,并且<script>是在<link>完全加载结束之后执行的。
测试3:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS/CSS</title> <script>var start = +new Date;</script>
<link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">
<script>
var endAfterCss = +new Date;
console.log("css", (endAfterCss - start));
</script> </head>
<body> <script src="http://udacity-crp.herokuapp.com/time.js?rtt=1&a"></script> <div id="result"></div> <script>
var endAfterScript = +new Date;
console.log("js",(endAfterScript - start));
</script> </body>
</html>
在console控制台的输出如下:

我们可以看到在两者之间还有一个外部的script标签,为什么两者的执行却是几乎同时发生的呢?
我们同样在network中刷新,然后得到的console控制台信息如下:

然后查看network,并查看外部css的详情, 如下所示:

可以看出,css的加载时间就是3.12s,然后它的加载阻塞了下面的script的执行,css一旦加载完毕,下面的script立即执行,所以得到了3118这个值。这个很容易理解。
注意观察上图,可以发现外部css和外部js的加载时间几乎是同时的,也就是说外部css的加载不会影响到下面的js的加载。
但是为什么在外部js文件下面的js却是3130呢? 外部的script的加载不是也需要一定的时间吗?我们看看js的加载时间。

我们可以看到,外部js的加载时间仅为1.38s,也就是说在外部css还没有加载完的时候js就加载结束了,但是它并没有执行,而是等到css加载完了之后才执行的。所以才会得到3130这个数值。其中的差值就是js执行的时间。
结论: 在css加载的过程中,下面的外部js同时也会加载,只是下面的外部js必须等到上面的css加载完成之后才能执行。 并且js会阻断下面的js的执行,因为js的执行是单线程的,所以在外部css执行结束之后,下面的内联css才会继续执行。
测试4:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS/CSS</title> <script>var start = +new Date;</script>
<link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">
<link rel="stylesheet" href="https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/mancard/css/card_min_dee38e45.css">
<script>
var endAfterCss = +new Date;
console.log("css", (endAfterCss - start));
</script> </head>
<body> <script src="http://udacity-crp.herokuapp.com/time.js?rtt=1&a"></script> <div id="result"></div> <script>
var endAfterScript = +new Date;
console.log("js",(endAfterScript - start));
</script> </body>
</html>
network如下:

即页面中的两个css是同时加载的,并且js也是,即两个css和js都是同时加载的,我的第二个css在html中是在js上面的,但是这里显示js却是先加载的,也就是说第一个css加载的时候,后面的js和css是同时加载的,至于谁最先加载,就不好说了,看下图,在代码没有改变的情况下,js是最后加载的。
说明:黄色部分为 Initial Connection ,即初始链接网络所消耗的时间,这种情况的发生往往是因为多个请求导致的。

如果我将耗时较长的css删除,那么我们得到的瀑布流如下所示:

可以看到这里确是js先加载的!
console控制台输出的结果是:

所以说link的加载不会影响js的加载是完全正确的。
结论: 如果同时具有两个link,一个外部的css,那么此三者是同时加载的,只是无法确定后面两者的先后关系。同样的,必须要在css加载结束之后js才能执行。
如果只有一个css、一个js,那么两者的加载顺序是不确定的。
测试5:
异步加载js
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script>var start = +new Date;</script>
<link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet"> </head> <body>
test
<script src="http://udacity-crp.herokuapp.com/time.js?rtt=1&a" async></script>
<div id="result"></div>
<script>
var end = +new Date;
console.log(end - start);
</script> </body>
</html>
表现如下:

可以看出,css的加载时间为2.37s, 在控制台的输出时间为2368ms,也就是说在css执行完成之后,外部js并没有阻碍下面的内联js的执行,而在页面中我们可以看到2094.6450000,这是指外联js执行的时间,我们在console控制台中可以看到外联js的执行时间为2.07s,也就是说在外联js加载完成之后就立即执行了,而没有等待外联css加载完毕再执行。
说明:再外联js的代码中我们使用了window.performance.now()方法,这个方法返回的是页面开启后的时间,且其单位为ms, 小数点之后保留了13位,这样的好处是较之于Data.now()更有利于我们检测性能。
更多关于window.performance.now()的内容可以参照这篇文章:http://www.cnblogs.com/xiaohuochai/archive/2017/03/09/6523397.html
结论: 使用了async属性之后,就可以实现js的异步加载,即该文件的执行不必等待外联css文件加载完成就可以执行,并且也不会阻塞后面的js的加载。
测试6:
创建<script>元素实现加载外部js
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script>var start = +new Date;</script>
<link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet"> </head> <body>
test
<script>
var script = document.createElement('script');
script.src = "http://udacity-crp.herokuapp.com/time.js?rtt=1&a";
document.getElementsByTagName('head')[].appendChild(script);
</script>
<div id="result"></div>
<script>var end = +new Date;document.getElementById("result").innerHTML = end-start;</script> </body>
</html>
我们可以看到瀑布流如下所示:

也就是说,在这种情况下,只有css完全加载完成之后,js才会加载。
结论: 在script标签是动态创建的情况下,其加载的优先级较低,会在css完全加载之后再加载。 注意观察: js的优先级为Low,所以会在css完全加载结束之后加载。
因为动态创建标签也是js语句,之前降到了语句的执行会被css阻塞。
测试7:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script>var start = +new Date;</script>
<link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">
<script>
var end0 = +new Date;
console.log(end0 - start);
</script> </head> <body>
<script src="http://udacity-crp.herokuapp.com/time.js?rtt=1&a"></script>
<div id="result"></div>
<script>
var end1 = +new Date;
console.log(end1 - start);
</script> <script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script>
<script>
var end2 = +new Date;
console.log(end2 - start);
</script> </body>
</html>
输出如下所示:

瀑布流如下所示:

可以看出css加载的过程中,后面的两个js同时加载,且加载的速度比css要快,这时css阻塞着后面的加载,一旦css加载完毕,已经加载好的js立即执行。
参考文章:http://www.cnblogs.com/shinnyChen/p/3762704.html
js、css的阻塞问题的更多相关文章
- 原来 CSS 与 JS 是这样阻塞 DOM 解析和渲染的
hello~各位亲爱的看官老爷们大家好.估计大家都听过,尽量将CSS放头部,JS放底部,这样可以提高页面的性能.然而,为什么呢?大家有考虑过么?很长一段时间,我都是知其然而不知其所以然,强行背下来应付 ...
- 定时器详解和应用、js加载阻塞、css加载阻塞
1.setTimeout().setInterval()详解和应用 1.1 详解: setTimeout.setInterval执行时机 1.2 存在问题: setInterval重复定时器可能存在的 ...
- 异步执行js脚本——防止阻塞
JS允许我们修改页面中的所有方面:内容,样式和用户进行交互时的行为. 但是js同样可以阻塞DOM树的形成并且延迟页面的渲染. 让你的js变成异步执行,并且减少不必要的js文件从而提高性能. JavaS ...
- electron之Windows下使用 html js css 开发桌面应用程序
1.atom/electron github: https://github.com/atom/electron 中文文档: https://github.com/atom/electron/tree ...
- JS/CSS缓存杀手——VS插件
背景 前些天去考科目二,感觉经历了一场不是高考却胜似高考的考试(10年前的5分之差, 还是难以释怀)! 一行八人,就我学的时间最少(4天,8人一辆车),教练都觉得我肯定还得再来一次! 靠着运气和 ...
- gulp实现打包js/css/img/html文件,并对js/css/img文件加上版本号
参考打包教程: http://www.cnblogs.com/tugenhua0707/p/4069769.html http://www.cnblogs.com/tugenhua0707/p/498 ...
- 配置springMVC之后,引入js,css等资源处理
配置了sringMVC之后,要引入js,css处理: 做法1:在<%page %>下面增加: <%@ taglib prefix="yesurl" uri=&qu ...
- springmvc js/css路径问题
①No mapping found for HTTP request with URI[/msm2/css/login2.css] in DispatcherServlet with name 'sp ...
- iOS之在webView中引入本地html,image,js,css文件的方法 - sky//////////////////////////////////////ZZZZZZZZZZZZZZZ
iOS之在webView中引入本地html,image,js,css文件的方法 2014-12-08 20:00:16CSDN-sky_2016-点击数:10292 项目需求 最近开发的项 ...
随机推荐
- DataGridView自定义行样式和行标题
定义两个样式对象: //定义两种行样式 private DataGridViewCellStyle m_RowStyleNormal; private DataGridViewCellStyle m_ ...
- vs2010 does not have a strong name
处理步骤: C:\myWorkSpace\IECG Dev. Tool\Forklift\DbUpgraderDLL\bin\Debug 为dll 所在目录 DbUpgraderDLL.dll为dll ...
- 严选 Android 路由框架优化(上篇)
0 背景 早前严选 Android 工程,使用原生 Intent 方式做页面跳转,为规范参数传递,做了编码规范,使用静态方法的方式唤起 Activity public static void star ...
- apache-jmeter-3.1的简单压力测试使用方法(下载和安装)
博客转载https://blog.csdn.net/lan_shu/article/details/55190127 压力测试工具LoadRunner是收费的,而且操作复杂.作为开发人员当然是用apa ...
- leecode刷题(3)-- 旋转数组
leecode刷题(3)-- 旋转数组 旋转数组 给定一个数组,将数组中的元素向右移动 K 个位置,其中 K 是非负数. 示例: 输入: [1,2,3,4,5,6,7] 和 k = 3 输出: [5, ...
- 16、OpenCV Python 腐蚀和彭胀
__author__ = "WSX" import cv2 as cv import numpy as np def erode_demo(image): print(image. ...
- 【BZOJ1047】[HAOI2007]理想的正方形 (倍增ST表)
[HAOI2007]理想的正方形 题目描述 有一个\(a*b\)的整数组成的矩阵,现请你从中找出一个\(n*n\)的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: ...
- bit、Byte、bps、Bps、pps、Gbps的单位的说明及换算
一.bit与Byte区别 1. bit(比特) 是电脑记忆体的最小单元,在二进制计算机中,每一比特代表0或1的数位信号. 2. Byte(单位字节) 一般表示存储介质大小的单位,数字.字母和特殊符号占 ...
- jquery 中 $('div','li')是什么意思?
Javascript 专业回答 2013-07-18 10:59 这个写法没有错误,而且那个人跟你说的也没错,是选择li里面所有div 前面几位都学艺不精,都说错了 要搞清楚$('div','l ...
- Octave安装符号工具箱
1.国内访问Octave的代码包不稳定,可以访问网址http://sourceforge.mirrorservice.org/o/oc/octave/Octave%20Forge%20Packages ...