【Hight Performance Javascript】——脚本加载和运行

脚本加载和运行

当浏览器遇到一个<script>标签时,无法预知javascript是否在<p>标签中添加内容。因此,浏览器停下来,运行javascript代码,然后继续解析、翻译页面。

浏览器必须首先下载外部文件的代码,这要占用一些时间,然后解析并运行代码,这又要占用一些时间。此过程中,页面解析和用户交互是被完全阻塞的。

将脚本放在底部

合并脚本减少个数

延迟脚本(defer)

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

defer属性指明元素中所包含的脚本不打算修改DOM,因此代码可以稍后执行。对应的Javascript文件将在<script>被解析时启动下载,但代码不会立即执行,直到DOM加载完成(在onload事件句柄被调用之前)。拥有defer属性的文件可以用页面的其他资源一起并行下载。

兼容性:只被IE 4+ 和FF 3.5+支持,在其他浏览器,defer属性被忽略。

动态异步加载脚本

动态脚本加载时非阻塞Javascript下载中最常用的模式,因为它可以跨浏览器,而且简单易用。

var script = document.createElement(‘script‘);
script.type = ‘text/javascript‘;
script.src = ‘file1.js‘;
document.getElementsByTagName(‘head‘)[0].appendChild(script);

无论在何处启动下载,文件的下载和运行都不会阻塞其他页面处理过程。甚至可以放在<head>部分。

当使用动态脚本节点下载时,返回的代码通常立即执行。当脚本是“自运行”类型时,这一机制运行正常,但如果脚本只包含供页面其他脚本调用的调用接口,则会带来问题。此时,需要跟踪脚本下载完成并准备妥善的情况。使用动态<script>节点发出时间得到相关信息:

function loadScript(url, cb) {
    var script = document.createElement(‘script‘);
    script.type = ‘text/javascript‘;
    if(script.readyState) {// IE
        script.onreadyStatechange = function () {
         if(script.readyState === ‘load‘ || script.readyState === ‘complete‘) {
             script.onreadystatechange = null;
             cb();
         }
        }
   }else {// Others
      script.onload = function () {
         cb();
        }
   }
    script.src = ‘file1.js‘;
    document.getElementsByTagName(‘head‘)[0].appendChild(script);
}

浏览器不保证文件加载的顺序,下面可以保证脚本按顺序下载并运行:

loadScript(‘file1.js‘,function () {
   loadScript(‘file2.js‘, function () {
      ...
    })
})

如果多个文件的次序十分重要,更好的方法是讲这些文件按照正确的次序连接成一个文件。

XHR 脚本注入

var xhr = new XMLHttpRequest();
xhr.open("get", "file1.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);

优点:下载不立即执行的javascript代码;同样的代码在所有现代浏览器中都不会引发异常。

缺点:Javascript文件必须与页面放置在同一个域内,不能从CDNs 下载。

推荐的非阻塞模式

推荐的向页面加载大量脚本的方法分为两个步骤:第一步,包含动态加载javascript所需的代码,然后加载页面初始化所需的除javascript之外的部分。这部分尽量小,可能只包含loadScript()函数。当初始代码准备好之后,用它来加载其余的javascript。例如:

<script type="text/javascript" src="loader.js"></script>
<script type="text/javascript">
    loadScript("the-rest.js", function(){
        Application.init();
    });
</script>
时间: 2024-12-25 14:47:44

【Hight Performance Javascript】——脚本加载和运行的相关文章

浏览器环境下JavaScript脚本加载与执行探析之动态脚本与Ajax脚本注入

在<浏览器环境下JavaScript脚本加载与执行探析之defer与async特性>中,我们研究了延迟脚本(defer)和异步脚本(async)的执行时机.浏览器支持情况.浏览器bug以及其他的细节问题.而除了defer和async特性,动态脚本和Ajax脚本注入也是两种常用的创建无阻塞脚本的方法.总的来看,这两种方法都能达到脚本加载不影响页面解析和渲染的作用,但是在不同的浏览器中,这两种技术所创建的脚本的执行时机还是有一定差异,今天我们再来探讨一下通过动态脚本技术和Ajax注入的脚本在这些方

javascript脚本加载

1.延迟脚本 脚本会被延迟到整个页面都解析完毕后再运行. 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <script type="text/javascript" defer="defer" src="test1.js"></script> 5 <script type="text/javascript" defer="

(转)高性能JavaScript:加载和运行(动态加载JS代码)

浏览器是如何加载JS的 当浏览器遇到一个<script>标签时,浏览器首先根据标签src属性下载JavaScript代码,然后运行JavaScript代码,继而继续解析和翻译页面.如果需要加载的js文件很多很大,则会让人感觉页面加载很慢,影响页面的交互.浏览器在遇到<body>之前,不会渲染页面的任何部分,如果此时<head>中需要加载的js文件很大的话,可能用户开始看到的页面就是一个“白板”,这种情况会立马让用户崩溃. Internet Explorer 8, Fir

浏览器环境下JavaScript脚本加载与执行探析之代码执行顺序

本文主要基于向HTML页面引入JavaScript的几种方式,分析HTML中JavaScript脚本的执行顺序问题 1. 关于JavaScript脚本执行的阻塞性 JavaScript在浏览器中被解析和执行时具有阻塞的特性,也就是说,当JavaScript代码执行时,页面的解析.渲染以及其他资源的下载都要停下来等待脚本执行完毕①.这一点是没有争议的,并且在所有浏览器中的行为都是一致的,原因也不难理解:浏览器需要一个稳定的DOM结构,而JavaScript可能会修改DOM(改变DOM结构或修改某个

高性能JavaScript之加载和运行

JavaScript 在浏览器中的性能,可认为是开发者所要面对的最重要的可用性问题.此问题因JavaScript的阻塞特征而复杂,也就是说,当JavaScript 运行时其他的事情不能被浏览器处理.事实上,大多数浏览器使用单进程处理UI 更新和JavaScript 运行等多个任务,而同一时间只能有一个任务被执行.JavaScript运行了多长时间,那么在浏览器空闲下来响应用户输入之前的等待时间就有多长. 从基本层面说,这意味着<script>标签的出现使整个页面因脚本解析.运行而出现等待.不论

JavaScript异步编程(二) 异步的脚本加载

异步的脚本加载 问题: <head>标签里的大脚本会滞压所有页面渲染工作,使页面在脚本加载完毕前一直处于白屏: <body>标签末尾的大脚本使用户只能看到静态页面,原本应进行渲染的地方却是空的: 解决方案: 对脚本分而治之; 负责让页面更好看.更好用的脚本立即加载,可稍后再加载的脚本稍后再加载. HTML5的async/defer属性 ?<script标签> 经典型和非阻塞型 理想情况下,脚本的加载应该与文档的加载同时进行,并且不影响DOM的渲染. 这样,一旦文档就绪就

JavaScript学习--Item26 异步的脚本加载

先来看这行代码: <script src = "allMyClientSideCode.js"></script> 这有点儿--不怎么样."这该放在哪儿?"开发人员会奇怪,"靠上点,放到<head>标签里?还是靠下点,放到<body>标签里?"这两种做法都会让富脚本站点的下场很凄惨.<head>标签里的大脚本会滞压所有页面渲染工作,使得用户在脚本加载完毕之前一直处于"白屏死机&

脚本加载

js脚本会阻塞页面其他资源的下载,直到其下载.解析.执行完毕.因为浏览器需要1个稳定的DOM树结构,而JS中很有可能有代码直接改变了DOM树结构,比如使用 document.write 或 appendChild,甚至是直接使用的location.href进行跳转,浏览器为了防止出现JS修改DOM树,需要重新构建DOM树的情况,所以 就会阻塞其他的下载和呈现. html.css.图片是可以并行加载的.当浏览器从服务器接收到了HTML文档,并把HTML在内存中转换成DOM树,在转换的过程中如果发现

不得不说的JavaScript异步加载

同步加载的问题 默认的js是同步加载的,这里的“加载”可以理解成是解析.执行,而不是“下载”,在最新版本的浏览器中,浏览器对于代码请求的资源都是瀑布式的加载,而不是阻塞式的,但是js的执行总是阻塞的.这会引起什么问题呢?如果我的index页面要加载一些js,但是其中的某个请求迟迟得不到响应,于是阻塞了后面的js代码的执行(同步加载),同时页面渲染也不能继续(如果js引入是在head标签后). <script type="text/javascript" src='http://c