js并行加载,顺序执行

<script>运行脚本或加载外部文件时,会阻塞页面渲染,阻塞其他资源的加载。如果页面中需要加载多个js文件,在古老浏览器中性能会比较糟糕。 因此有了最原始的优化原则:把脚本放在底部

如何实现js非阻塞、并行加载,甚至能保持执行顺序呢?各浏览器表现如何?站在巨人的肩膀上,Kyle SimpsonNicholas C. ZakasSteve Souders对此有过总结和方案。

背景

1. Script DOM Element。 动态插入<script>,不会阻塞,但无法保持执行顺序。但唯有Firefox可以保持执行顺序,但也差点在Firefox 4 nightly的版本中去掉这个特性。

2. HTML5 async 非阻塞,加载完后立即执行,不保证顺序。这个属性不管有没有值、值为true或false,都是等同的效果(由于Kyle的推进,不能保证执行顺序与其值无关了)。

Google Analytics的新版嵌入代码就结合使用了上面两个方案,如:

1
2
3
4
5
6
7
8
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www')
          + '.google-analytics.com/ga.js';
 
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);

3. IE partsandspares.co.za defer属性。不阻塞,可以保证顺序,在DOM加载完成后执行(在DOMContentLoaded之前)。

4. <script>的type属性设为”script/cache” 非标准的type属性,使js文件只会被加载而不会执行。需要执行时,创建一个type属性为”text/javascript”的正常<script>元素,src设为前面已经加载的js地址即可,执行顺序开发者可控(执行时机也完全可控)。类似的方式也有通过<img>来做预加载的。

5. document.write。文档流关闭后执行会清空整个页面。

6. XHR 并行加载,执行顺序可控,但有同域限制。

基本需求

Steve Souders 和 Nicholas C. Zakas 一起总结了下,认为js加载方案必须解决以下问题

  1. 支持特性检测
  2. 不会重复加载
  3. 支持并行加载

开发者的美好愿望

Nicholas C. Zakas 几经周折,有了以下的提案,分离js的加载和执行,方便开发者自由控制js的执行时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
var script = document.createElement("script");
 
// 此属性仅可由js动态写入,在HTML标签中直接写入无效
script.preload = true;
 
// src赋值后,立即触发加载(仅加载,不会执行js内容)
script.src = "foo.js";
 
// onpreload是需要新支持的事件,加载完成后触发此事件
script.onpreload = function(){
    // 在需要时,将加载的js插入到DOM中,即可运行生效
    document.body.appendChild(script);
};

基于特性检测feature detection(区别于特性推测feature inference)

var isPreloadSupported = (typeof script.preload == “boolean”);

这一特性只有在Javascript中动态赋值时生效,直接写到HTML标签上时是无效的。

但这只是一个提案,开发者们的美好愿望,而非被浏览器支持的标准。目前这一提案已在LABjs中支持,Zakas本人也在积极推进此提案的标准化。

而Kyle在推进另外一种方式,即要求对含有属性async=false的<script>保持执行顺序。如果async=true,则一旦加载完则会马上执行脚本,不会严格保持顺序。默认地,页面中的<script>的async属性为false,即保持执行顺序;js创建的<script>的async属性为true,即加载完立即执行,不保证顺序。

为了支持特性检测,一个由js创建的<script>标签默认具有async=true的属性。

Kyle的这一提案已被HTML5小组接受放入草案,在Firefox 4 nightly版本中的也已实现。

Firefox 4为了更向HTML5标准看齐,一度在开发者版本中去掉了对动态创建<script>来加载js文件的执行顺序支持

<script> elements created using document.createElement() and inserted into a document now behave according to the HTML5 specification by default. Scripts with the src attribute execute as soon as available (without maintaining ordering) and scripts without the src attribute execute synchronously.

为此,Kyle向WebKit开发团队抗议,提了一个bug,最终得到了如他所愿的支持:

To make script-inserted scripts that have the src attribute execute in the insertion order, set .async=false on them.

Zakas很欣赏Kyle的方案,Kyle在LABjs中也支持了Zakas的提议,各浏览器们也这么和谐就好了。

转自:http://www.impng.com/web-dev/parallel-download-ordered-execute.html

js并行加载,顺序执行的更多相关文章

  1. JS 动态加载脚本 执行回调

    JS 动态加载脚本  执行回调 关于在javascript里面加载其它的js文件的问题可能很多人都遇到过,但很多朋友可能并不知道怎么判断我们要加载的js文件是否加载完成,如果没有加载完成我们就调用文件 ...

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

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

  3. JS的加载和执行

    从JS的加载和执行谈性能优化 ---高性能JS读后感(第一章) 从脚本的"霸道"说起,随着浏览器的进步,js越来越听话了,所以,我们先说说以前的浏览器是怎么加载js的,以及js如何 ...

  4. 性能优化-css,js的加载与执行

    前端性能优化 css,js的加载与执行 javascript是单线程的 一个网站在浏览器是如何进行渲染的呢? html页面加载渲染的过程 html渲染过程的一些特点 顺序执行,并发加载 词法分析 并发 ...

  5. promise实现图片按照指定的加载顺序执行

    promise实现图片按照指定的加载顺序执行,先加载第二张,再加载第一张,最后加载第三张 <!DOCTYPE html> <html lang="en"> ...

  6. JS 动态加载脚本 执行回调_转

    关于在javascript里面加载其它的js文件的问题可能很多人都遇到过,但很多朋友可能并不知道怎么判断我们要加载的js文件是否加载完成,如果没有加载完成我们就调用文件里面的函数是不会成功的.本文讲解 ...

  7. JS脚本加载与执行对性能的影响

    高性能JavaScript-JS脚本加载与执行对性能的影响 在web产品优化准则中,很重要的一条是针对js脚本的加载和执行方式的优化.本篇文章简单描述一下其中的优化准则. 1. 脚本加载优化 1.1 ...

  8. 前端性能优化 css和js的加载与执行

    一个网站在浏览器端是如何进行渲染的? html本身首先会被渲染成 DOM 树,实际上 html 是最先通过网址请求过来的,请求过来之后,html 本身会由一个字节流转化成一个字符流,浏览器端拿的就是字 ...

  9. 【转】html、css、js文件加载顺序及执行情况

    原链接:http://www.cnblogs.com/Walker-lyl/p/5262075.html 今天看书,看到html,css,js加载执行情况,发现自己并不是真正的了解,网上搜了半小时依然 ...

随机推荐

  1. LoadRunner性能测试-loadrunner事务

    事务(Transaction): 简单来说就是用来模拟用户的一个相对完整的业务过程.添加事务,是用来衡量响应时间的重要方法.我们可以通过事务计时来对不同压力负载下的性能指标进行对比. 插入事务的方法: ...

  2. 学生问的一道javascript面试题[来自腾讯]

    function Parent() { this.a = 1; this.b = [1, 2, this.a]; this.c = { demo: 5 }; this.show = function ...

  3. 27. leetcode 401. Binary Watch

    A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 LEDs on the bottom ...

  4. 谈谈渲染,玩玩nginx——前后端分离,转发请求到Tomcat的尝试

    一.谈谈"渲染" 相信好多人都挺听过"渲染"这个词,但不清楚它是什么意思?前端开发以为这是后端的活儿,后端开发以为是前端的事儿,推着推着就不了了之.其实渲染很简 ...

  5. There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

    解题思路:合并两个数组,创建一个 Map对象,用以存放排好顺序的键值对,键为序号,值为数组值,中位数的结果分两种情况讨论: 1.m+n为奇数:(m+n)/2为中位数 2.m+n为偶数:(((m+n)/ ...

  6. javascript 用Activex方法调用数据库中的数据,只可用于IE

    // JavaScript source code //创建数据库连接对象 var conn = new ActiveXObject("ADODB.Connection"); // ...

  7. vue学习笔记(1)—— 组件化实现todoList

    一.环境搭建 1.npm 大型应用时推荐用npm安装,npm能很好的和webpack等模块打包器配合使用.具体安装步骤请参考网上的诸多教程.完成后使用如下命令安装vue. $ npm install ...

  8. jQuery之jquery.lazyload.js插件用法

    研究背景:网站中如果图片过多,就会因为加载图片而等待很长时间,此时我们就用到图片延时加载插件jquery.lazyload.js,这个插件可以让我们在向下滚动的时候加载图片.让网页首屏尽可能快的加载进 ...

  9. C# 开机自启动和最小化托盘显示

    C# 开机自启动和最小化托盘显示 一.      C# 开机自启动 C# 开机自启动,这个功能是大多数服务型软件很常用一个功能,但是这个功能确是不 太好做,花了两天想对策.不过最终呢,结果还是很满意的 ...

  10. 解析SS、SP、BP寄存器

    SS, SP, BP 三个寄存器 SS:存放栈的段地址: SP:堆栈寄存器SP(stack pointer)存放栈的偏移地址; BP: 基数指针寄存器BP(base pointer)是一个寄存器,它的 ...