提高js加载速度,实现js无阻塞加载方式,高性能的加载执行JavaScript

时间: 2017-11-01阅读: 605标签: js知识

由于js的堵塞特性,当浏览器在加载javascript代码时,不能同时做其他任何事情,如果javascript执行时间越久,浏览器等待响应的时间就越久。所以为了解决防止先执行js代码,然后再继续页面的解析和渲染,我们一般采用调整js脚本的位置,通过采用将所有的<script>标签尽可能的放在<body>标签的底部,来减少对整个页面加载的影响。

如果js文件比较多,会产生大量的Http请求,我们都知道http请求是比较耗费性能的事情,例如你加载1个100kb的文件比加载10个10Kb的文件速度要快,因此我们会采用合并压缩js脚本来达到优化速度的效果,当然有许多出色的工具可以加快JavaScript装入的速度。比如Lab.js,使用它你就可以并行装入JavaScript文件,加快总的装入过程。你还可以为需要装入的脚本设置某个顺序,那样就能确保依赖关系的完整性。而且开发者声称其网站上的速度提升了2倍。

除了上述内容以外,这篇文章主要讲解如果延时加载js和动态加载js,达到页面无堵塞的效果。

js的延时加载

defer的使用 

defer是一个常用的优化方案,它表示脚本会被延迟到文档完全被解析和显示之后再执行,加载后续文档元素的过程将和js脚本的加载并行进行(异步),这样页面加载会更快。  

<script src="main.js" defer></script>


async的使用  

async是html5的属性,async 属性规定一旦脚本可用,则会异步执行。async不保证按照脚本出现的先后顺序执行,因此,确保两者之前互不依赖非常重要,指定async属性的目的是不让页面等待两个脚本的下载和执行,从而异步加载页面其他内容,异步脚本一定会在页面的load事件前执行,但可能会在DOMContentLoaded事件触发之前或之后执行。支持异步脚本的浏览器有Firefox 3.6、Safari 5 和Chrome。

<script async src="main.js"></script>


注意点

1、建议异步脚本不要在加载期间修改DOM,当js不需要改变DOM结构时推荐使用异步加载(比如一些统计代码,它与页面执行逻辑无关,也不会改变DOM结构)。

2、延迟脚本并不一定会按照顺序执行,因此,确保两者之前互不依赖非常重要。


js的动态加载


由于文档对象模型(DOM)允许您使用 JavaScript 动态创建 HTML 的几乎全部文档内容。  当然也就应许我们动态创建<script>元素,例如:
function loadScript(url, callback){
 var script = document.createElement ("script")
 script.type = "text/javascript";
 if (script.readyState){ //IE
  script.onreadystatechange = function(){
   if (script.readyState == "loaded" || script.readyState == "complete"){
    script.onreadystatechange = null;
    callback();
   }
  };
 }else{ //Others
  script.onload = function(){
   callback();
  };
 }
 script.src = url;
 document.getElementsByTagName("head")[0].appendChild(script);
}

说明:此方法让元素添加到页面之后立刻开始下载。此技术的重点在于:无论在何处启动下载,文件的下载和运行都不会阻塞其他页面处理过程。您甚至可以将这些代码放在<head>部分而不会对其余部分的页面代码造成影响(除了用于下载文件的 HTTP 连接)。使用上述方法:

loadScript("main.js", function(){
   console.log("File is loaded!");
});

如何需要在页面中动态加载很多 JavaScript 文件,我们可以在回调方法中多次调用即可。


js动态注入

创建一个XMLHttpRequest对象,然后下载 JavaScript 文件,接着用一个动态 <script> 元素将 JavaScript 代码注入页面。例如:

var xhr = new XMLHttpRequest();
xhr.open("get", "main.js", true);
xhr.onreadystatechange = function(){
 if (xhr.readyState == 4){
  if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
   var script = document.createElement ("script");
   script.type = "text/javascript";
   script.text = xhr.responseText;
   document.body.appendChild(script);
  }
 }
};
xhr.send(null);

向服务器发送一个GET 请求 ,去获取main.js文件,当状态成功,我们把获取的js文件动态加载到页面。采取了它的好处是:它下载后不会自动执行,这使得您可以推迟执行,直到一切都准备好了。另一个优点是,同样的代码在所有现代浏览器中都不会引发异常。需要注意的是,加载的js文件不能跨域获取,所以一般网站通常不采用 XHR 脚本注入技术。


总结:

1. 尽可能的将<script>标签放到页面底部,也就是</body>闭合标签之前,这能确保在脚本执行前页面已经完成了渲染。

2.尽可能的合并js文件。减少http请求,加载速度也就越快。

3.尽可能的压缩js文件。减少文件体积,加快加载的速度。

4.<script>标签使用defer或async属性。异步加载js。

5.使用动态创建的<script>元素来下载并执行代码。

6.使用 XHR 对象下载 JavaScript 代码并注入页面中。



js中减少使用不必要的if-else或switch_利用数组/对象代替if-else,switch

无论使用if-else,还是switch。当条件多的时候代码显得非常冗长,而且每次添加条件时需要修改主流程的代码,这样就破坏了类的开闭原则。为解决日后的维护可能存在问题,我们可以采用另一种比较优雅的实现方式来替换if-else,switch吗?

JavaScript深入之参数按值传递

ECMAscript中所有函数的参数都是按值传递,也就是,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。js始终是按值传递,在这里称他为共享传递。

为什么尽量别用setInterval

在开发一个在线聊天工具时,经常会有过多少毫秒就重复执行一次某操作的需求。“没问题”,大家都说,“用setInterval好了。”我觉得这个点子很糟糕。

avaScript与WebAssembly进行比较+在哪些情况下会优于JavaScript

这是专门探索JavaScript及其构建组件的系列,在识别和描述核心元素的过程中,我们还分享了构建SessionStack时使用的一些经验法则,这是一个轻量级但健壮且高性能的JavaScript应用程序,以帮助用户实时查看和重现其Web应用程序的缺陷。

js判断是否为IE浏览器的多种方法总汇

这篇文章主要整理通过js来判断浏览器是否为IE的多种方法。使用js脚本判断浏览器是否为ie,这里分享六种判断是否为ie的方法,有需要的朋友参考学习下。

js中return关键词的作用_return的用法详解

return从字面意思来看就是返回,官方定义return语句将终止当前函数并可以返回当前函数的值; 也就是说return后面可以跟一个value,也就是说可以跟javascript中的任何数据类型

js记录用户行为浏览记录和停留时间

原来是想使用 cookie 来记录,但是考虑到 cookie 所能记录的数据最大为 4k ,可能不够用。于是使用了 HTML5 的 localStorage (最大数据 5M )来存储( IE8 以上浏览器支持)。这里使用到了 jquery.cookie 的插件,所以页面要引入 jquery 和 jquery.cookie 。

Web Worker 详细介绍_Web Workers的使用

web worker 是运行在后台的 JavaScript,独立于其他脚本,也就是说在Javascript单线程执行的基础上,开启一个子线程,进行程序处理,而不影响主线程的执行。Service Worker 是一个由事件驱动的 worker,它由源和路径组成,以加载 .js 文件的方式实现的。

数字在JavaScript中是如何编译的

JavaScript中的所有数字都是浮点数。这篇博客文章解释了这些浮点数如何在64位二进制内部表示。浮点数并不一定等于小数,定点数也并不一定就是整数。所谓浮点数就是小数点在逻辑上是不固定的,而定点数只能表示小数点固定的数值

window.location.href的用法(动态输出跳转)

javascript中的location.href有很多种用法,window.location.href 语句可以实现一个框架的页面在执行服务器端代码后刷新另一个框架的页面