javascript无阻塞加载脚本

简介: javascript无阻塞加载脚本1 脚本阻塞并行下载行内脚本通过script标签引入整段javascript:12345function displayMessage(msg){ alert(msg);}  外部脚本通过script的src属性把独立文件中的JavaScript引入:src属性定义了需加载的外部URL,如果缓存中有脚本文件,浏览器就从缓存中读取,否则就发送HTTP请求获取。

javascript无阻塞加载脚本
1 脚本阻塞并行下载
行内脚本通过script标签引入整段javascript:

1
2
3
4
5

function displayMessage(msg){
    alert(msg);

}

  外部脚本通过script的src属性把独立文件中的JavaScript引入:

src属性定义了需加载的外部URL,如果缓存中有脚本文件,浏览器就从缓存中读取,否则就发送HTTP请求获取。

浏览器在下载和执行脚本时出现阻塞的原因:1 document.write改变了页面 2 其中一个js依赖于另一个js(浏览器要确保要确保脚本在HTML文档中出现的顺序来执行;否则可能会出现竞争状态;可以按顺序执行,但不一定要按顺序下载)。

2 更好的运行脚本
  方案:1 把所有javascript内嵌到页面中(少量是可以的;由于通常页面大小和缓存能带来更多好处,因此推荐外部引入javascript)
  下面这些技术既可以避免因阻塞导致的减速影响,由拥有脚本的好处(可以并行运行脚本)。

   (1)XHR Eval。

   (2)XHR注入(XHR Injection)。

   (3)Script in Iframe。

   (4)Script Dom Element。

   (5)Script Defer。

   (6)document.write Script Tag。

   XHR Eval (XMLHttpRequest(XHR)从服务端获取脚本;当响应完成时,通过eval命令执行内容)

  缺点:通过MLHttpRequest获取的脚本必须部署在和主页面相同的域中。以下是XH Eval相关代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var xhrObj = getXHRObject();
xhrObj.onreadystatechange =
function(){

if ( xhrObj.readyState == 4 && 200 == xhrObj.status ){
  eval (xhrObj.responseText);
}

};
xhrObj.open("GET", 'A.js', true);//必须和主页面在·同一个域中
xhrObj.send("");

function getXHRObject() {

var xhrObj = false;
try{
  xhrObj = new XMLHttpRequest();
}
catch(e){
  var progid = ["MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"];
  for( var i = 0;i< progid.length; ++i){
    try{
      xhrObj =  new ActiveXObject(progid[i]);
    }
    catch(e){
      continue;
    }
    break;
  }
}
finally {
  return xhrObj;
}

}
  XHR注入(通过创建一个script的DOM元素,然后把XMLHttpRequest的响应注入script中执行javascript;通过XMLHttpRequest获取的内容必须部署在和主页面相同的域中。)XHRInjection代码如下:
1
2
3
4
5
6
7
8
9
10
11
var xhrObj = getXHRObject();
xhrObj.onreadystatechange =
function (){

if (xhrObj.readyState == 4 ){
  var scriptElem = document.createElement("script");
  document.getElementsByTagName('head')[0].appendChild(scriptElem);
  scriptElem.text = xhrObj.responseText;
}

};
xhrObj.open ('GET', 'a.JS', true);
xhrObj.send('');
  Script in Iframe
  iframe URL和主页面同域。即使主页面同域,我们任然要修改javascript来创建他们之间的关联。

  方案一:

  //使用“frames”访问主页面上的iframe

  window.frames[0].createNewDiv();

  //使用“getElementById”访问主页面上的iframe

  document.getElementById('frame').contentWindow.createNewDiv();

  方案二:

  //ifame使用parent变量引用父页面:

  //在iframe中使用“parent”访问主页面

  function createNewDiv(){

    var newDiv = parent.document.createElemnent('div');

    parent.document.body.appendChild(newDiv);

  }  

  //iframe自身的消耗比较高

  Script Dom Element
  相对于在HTML中使用script标签下载脚本文件而言,该技术使用JavaScript动态地创建script DOM 元素并设置src属性,这只要两三行javascript代码就可以实现。

  var scriptElem = document.createElement('script');

  scriptElem.src = 'http://anydomain.com/A.js' ;

  document.getElementByTagName('head')[0].appendChild(scriptElem);

  //这种方式下载脚本不会阻塞其它组件。允许跨域获取脚本。外部脚本可以直接调用。

  //script DOM Element http://stevesouders.com/cuzillin/?ex=10010&title=Script+Dom+Element

  ,浏览器还有ScriptnDefer以及document.write ScriptTag 我这里就不一一介绍了。 

3、浏览器忙指示器
  浏览器忙指示器,让用户感知到页面还在加载。浏览器忙指示器包括:状态栏、进度条、标签页图标和光标。

  另外两个浏览器忙指示器是组赛渲染和阻塞onload事件。缺点:当使用SCRIPT SRC技术下载脚本时,浏览器停止渲染所有脚本后面的内容。通常页面的onload事件要等到所有页面下载完时才会触发。如果让状态栏等待更长时间,才显示“完成”,并且默认输入框取焦点,影响用户体验。(忙指示器是否出发,是所使用的技术和浏览器共同决定的)

4、确保(或避免)按顺序执行
  很多网页都包含多个有特定依赖顺序的脚本,它们会按照到达的顺序执行——最先到达,最先执行。这会导致竞争状态,进而导致未定义标识符错误。要想是浏览器按照顺序执行,而不是加载的顺序执行,可以使用Script Defer 和document.write ScriptTag保证脚本按照顺序执行。

  (脚本按照特定顺序执行并非总那么重要,有时候按照加载的顺序执行,可以快速的渲染页面。)

  不推荐使用document.write Script Tag技术。因为它只在部分浏览器中实现并行下载,而且还阻塞脚本之外所有其它资源的下载。Script Defer技术也只在部分浏览器中实现了并行下载。

  当脚本与主页面同域时,XHR Eval 、XHR 注入和Script in Iframe可以满足需求。但如果使用XHR Eval 或Script in Iframe技术,我们需要重构一部分脚本,而XHR注入和Script DOM Element技术可以直接使用现有的脚本文件,无需任何改动。

5、最佳方案
  根据项目需求·合理选择最佳的技术。有下面六种情况:

  有不同域、无序

  不同域,保持顺序

  同域、无序、无忙指示器

  同域、无序、有忙指示器

  同域、保持顺序、无忙指示器

  同域、保持顺序、由忙治时期

  开发者可以通过该函数来确保按最佳方案加载脚本,原理如下:

  function loadScript(url, bPreserverOrder, bShowBusy);
原文地址https://www.cnblogs.com/yaosusu/p/11275507.html

相关文章
|
2月前
|
缓存 JavaScript 前端开发
高效打造跨平台桌面应用:Electron加载服务器端JS
【9月更文挑战第17天】Electron 是一个基于 Chromium 和 Node.js 的开源框架,允许使用 HTML、CSS 和 JavaScript 构建跨平台桌面应用。加载服务器端 JS 可增强应用灵活性,实现代码复用、动态更新及实时通信。通过 HTTP 请求、WebSocket 或文件系统可实现加载,但需注意安全性、性能和兼容性问题。开发者应根据需求选择合适方法并谨慎实施。
142 3
|
21天前
|
JSON 移动开发 JavaScript
在浏览器执行js脚本的两种方式
【10月更文挑战第20天】本文介绍了在浏览器中执行HTTP请求的两种方式:`fetch`和`XMLHttpRequest`。`fetch`支持GET和POST请求,返回Promise对象,可以方便地处理异步操作。`XMLHttpRequest`则通过回调函数处理请求结果,适用于需要兼容旧浏览器的场景。文中还提供了具体的代码示例。
在浏览器执行js脚本的两种方式
|
11天前
|
缓存 前端开发 JavaScript
优化CSS和JavaScript加载
Next.js和Nuxt.js在优化CSS和JavaScript加载方面提供了多种策略和工具。Next.js通过代码拆分、图片优化和特定的CSS/JavaScript优化措施提升性能;Nuxt.js则通过代码分割、懒加载、预渲染静态页面、Webpack配置和服务端缓存来实现优化。两者均能有效提高应用性能。
|
2月前
|
JavaScript 前端开发
用JavaScript脚本将当地时间转换成其它时区
用JavaScript脚本将当地时间转换成其它时区
|
3月前
|
编解码 缓存 算法
Three.js如何降低3D模型的大小以便更快加载
为加快600MB的3D模型在Three.js中的加载速度,可采用多种压缩方法:1) 减少顶点数,使用简化工具或LOD技术;2) 压缩纹理,降低分辨率或转为KTX2等格式;3) 采用高效文件格式如glTF 2.0及draco压缩;4) 合并材质减少数量;5) 利用Three.js内置优化如BufferGeometry;6) 按需分批加载模型;7) Web Workers后台处理;8) 多模型合并减少绘制;9) 使用Texture Atlas及专业优化工具。示例代码展示了使用GLTFLoader加载优化后的模型。
431 12
|
3月前
|
前端开发 JavaScript Linux
【Azure 应用服务】在Azure App Service for Linux环境中,部署的Django应用,出现加载css、js等静态资源文件失败
【Azure 应用服务】在Azure App Service for Linux环境中,部署的Django应用,出现加载css、js等静态资源文件失败
|
3月前
|
JavaScript 前端开发
JavaScript引入全攻略:提升网页加载速度的秘诀!
JavaScript引入全攻略:提升网页加载速度的秘诀!
|
3月前
|
资源调度 JavaScript 前端开发
如何大幅减少 Vue.js 中的包大小和加载时间,提升用户体验!
如何大幅减少 Vue.js 中的包大小和加载时间,提升用户体验!
|
4月前
|
监控 JavaScript 前端开发
Node中的AsyncLocalStorage 使用问题之Node.js内部模块和外部模块的加载的问题如何解决
Node中的AsyncLocalStorage 使用问题之Node.js内部模块和外部模块的加载的问题如何解决
|
4月前
命令行加载特效 【cli-spinner.js】 实用教程
命令行加载特效 【cli-spinner.js】 实用教程
48 0