【问题标题】:load scripts asynchronously异步加载脚本
【发布时间】:2011-12-04 20:36:16
【问题描述】:

我正在使用来自 JQuery 的几个插件、自定义小部件和一些其他库。结果我有几个 .js 和 .css 文件。我需要为我的网站创建一个加载器,因为它需要一些时间来加载。如果我可以在导入所有内容之前显示加载器,那就太好了:

<script type="text/javascript" src="js/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="js/myFunctions.js"></script>
<link type="text/css" href="css/main.css" rel="stylesheet" />
... 
....
 etc

我找到了一些教程,使我能够异步导入 JavaScript 库。例如我可以这样做:

  (function () {
        var s = document.createElement('script');
        s.type = 'text/javascript';
        s.async = true;
        s.src = 'js/jquery-ui-1.8.16.custom.min.js';
        var x = document.getElementsByTagName('script')[0];
        x.parentNode.insertBefore(s, x);
    })();

由于某种原因,当我对所有文件执行相同操作时,页面无法正常工作。我已经尝试了很长时间试图找出问题所在,但我就是找不到。首先我认为这可能是因为某些 javascript 函数依赖于其他函数。但是当一个完成时我使用超时功能以正确的顺序加载它们我继续下一个并且页面仍然表现得很奇怪。例如,我无法点击链接等...虽然动画仍然有效..

无论如何

这是我一直在想的……我相信浏览器有缓存,这就是为什么第一次加载页面需要很长时间而下一次加载速度很快的原因。所以我想做的是用一个异步加载所有这些文件的页面替换我的 index.html 页面。当 ajax 完成加载所有这些文件时,重定向到我计划使用的页面。使用该页面时,加载时间不会很长,因为文件应该已经包含在浏览器的缓存中。在我的索引页面(.js 和 .css 文件异步加载的页面)上,我不在乎出现错误。完成后我只会显示一个加载器并重定向页面......

这个想法是一个不错的选择吗?还是我应该继续尝试实现异步方法?


编辑

我异步加载所有内容的方式是这样的:

importScripts();

function importScripts()
{
    //import: jquery-ui-1.8.16.custom.min.js
    getContent("js/jquery-1.6.2.min.js",function (code) {
                var s = document.createElement('script');
                s.type = 'text/javascript';
                //s.async = true;
                s.innerHTML=code;
                var x = document.getElementsByTagName('script')[0];
                x.parentNode.insertBefore(s, x);
                setTimeout(insertNext1,1);
            });


    //import: jquery-ui-1.8.16.custom.min.js
    function insertNext1()
    {
        getContent("js/jquery-ui-1.8.16.custom.min.js",function (code) {
                    var s = document.createElement('script');
                    s.type = 'text/javascript';
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext2,1);
                });
    }

    //import: jquery-ui-1.8.16.custom.css
    function insertNext2()
    {

        getContent("css/custom-theme/jquery-ui-1.8.16.custom.css",function (code) {
                    var s = document.createElement('link');
                    s.type = 'text/css';
                    s.rel ="stylesheet";
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext3,1);
                });
    }

    //import: main.css
    function insertNext3()
    {

        getContent("css/main.css",function (code) {
                    var s = document.createElement('link');
                    s.type = 'text/css';
                    s.rel ="stylesheet";
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext4,1);
                });
    }

    //import: jquery.imgpreload.min.js
    function insertNext4()
    {
        getContent("js/farinspace/jquery.imgpreload.min.js",function (code) {
                    var s = document.createElement('script');
                    s.type = 'text/javascript';
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext5,1);
                });
    }


    //import: marquee.js
    function insertNext5()
    {
        getContent("js/marquee.js",function (code) {
                    var s = document.createElement('script');
                    s.type = 'text/javascript';
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext6,1);
                });
    }


    //import: marquee.css
    function insertNext6()
    {

        getContent("css/marquee.css",function (code) {
                    var s = document.createElement('link');
                    s.type = 'text/css';
                    s.rel ="stylesheet";
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext,1);
                });
    }



    function insertNext()
    {
        setTimeout(pageReadyMan,10);        
    }
}


// get the content of url and pass that content to specified function
function getContent( url, callBackFunction )
{
     // attempt to create the XMLHttpRequest and make the request
     try
     {
        var asyncRequest; // variable to hold XMLHttpRequest object
        asyncRequest = new XMLHttpRequest(); // create request object

        // register event handler
        asyncRequest.onreadystatechange = function(){
            stateChange(asyncRequest, callBackFunction);
        } 
        asyncRequest.open( 'GET', url, true ); // prepare the request
        asyncRequest.send( null ); // send the request
     } // end try
     catch ( exception )
     {
        alert( 'Request failed.' );
     } // end catch
} // end function getContent

// call function whith content when ready
function stateChange(asyncRequest, callBackFunction)
{
     if ( asyncRequest.readyState == 4 && asyncRequest.status == 200 )
     {
           callBackFunction(asyncRequest.responseText);
     } // end if
} // end function stateChange

奇怪的部分是所有样式的工作加上所有 javascript 函数。页面由于某种原因被冻结了......

【问题讨论】:

    标签: javascript ajax html asynchronous


    【解决方案1】:

    对于 HTML5,您可以使用“预取”

    &lt;link rel="prefetch" href="/style.css" as="style" /&gt;

    看看 js 的“预加载”。

    &lt;link rel="preload" href="used-later.js" as="script"&gt;

    【讨论】:

      【解决方案2】:

      您可能会觉得这篇 wiki 文章很有趣:http://ajaxpatterns.org/On-Demand_Javascript

      它解释了如何以及何时使用这种技术。

      【讨论】:

      • 不幸的是,链接似乎已失效。 :(
      • @Eric 这是因为这是一种古老的动态加载代码的方法:D
      【解决方案3】:

      如果有人想在 React 中使用它,这里有一个小的 ES6 函数

      import {uniqueId} from 'lodash' // optional
      /**
       * @param {String} file The path of the file you want to load.
       * @param {Function} callback (optional) The function to call when the script loads.
       * @param {String} id (optional) The unique id of the file you want to load.
       */
      export const loadAsyncScript = (file, callback, id) => {
        const d = document
        if (!id) { id = uniqueId('async_script') } // optional
        if (!d.getElementById(id)) {
          const tag = 'script'
          let newScript = d.createElement(tag)
          let firstScript = d.getElementsByTagName(tag)[0]
          newScript.id = id
          newScript.async = true
          newScript.src = file
          if (callback) {
            // IE support
            newScript.onreadystatechange = () => {
              if (newScript.readyState === 'loaded' || newScript.readyState === 'complete') {
                newScript.onreadystatechange = null
                callback(file)
              }
            }
            // Other (non-IE) browsers support
            newScript.onload = () => {
              callback(file)
            }
          }
          firstScript.parentNode.insertBefore(newScript, firstScript)
        } else {
          console.error(`The script with id ${id} is already loaded`)
        }
      }

      【讨论】:

        【解决方案4】:

        我写了一个小帖子来帮助解决这个问题,您可以在https://timber.io/snippets/asynchronously-load-a-script-in-the-browser-with-javascript/ 阅读更多内容,但我在下面附上了帮助程序类。它会自动等待脚本加载并返回指定的窗口属性。

        export default class ScriptLoader {
          constructor (options) {
            const { src, global, protocol = document.location.protocol } = options
            this.src = src
            this.global = global
            this.protocol = protocol
            this.isLoaded = false
          }
        
          loadScript () {
            return new Promise((resolve, reject) => {
              // Create script element and set attributes
              const script = document.createElement('script')
              script.type = 'text/javascript'
              script.async = true
              script.src = `${this.protocol}//${this.src}`
        
              // Append the script to the DOM
              const el = document.getElementsByTagName('script')[0]
              el.parentNode.insertBefore(script, el)
        
              // Resolve the promise once the script is loaded
              script.addEventListener('load', () => {
                this.isLoaded = true
                resolve(script)
              })
        
              // Catch any errors while loading the script
              script.addEventListener('error', () => {
                reject(new Error(`${this.src} failed to load.`))
              })
            })
          }
        
          load () {
            return new Promise(async (resolve, reject) => {
              if (!this.isLoaded) {
                try {
                  await this.loadScript()
                  resolve(window[this.global])
                } catch (e) {
                  reject(e)
                }
              } else {
                resolve(window[this.global])
              }
            })
          }
        }
        

        用法是这样的:

        const loader = new Loader({
            src: 'cdn.segment.com/analytics.js',
            global: 'Segment',
        })
        
        // scriptToLoad will now be a reference to `window.Segment`
        const scriptToLoad = await loader.load()
        

        【讨论】:

          【解决方案5】:

          这是我消除渲染阻塞 JavaScript 的自定义解决方案:

          // put all your JS files here, in correct order
          const libs = {
            "jquery": "https://code.jquery.com/jquery-2.1.4.min.js",
            "bxSlider": "https://cdnjs.cloudflare.com/ajax/libs/bxslider/4.2.5/jquery.bxslider.min.js",
            "angular": "https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.2/angular.min.js",
            "ngAnimate": "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.2/angular-animate.min.js"
          }
          const loadedLibs = {}
          let counter = 0
          
          const loadAsync = function(lib) {
            var http = new XMLHttpRequest()
            http.open("GET", libs[lib], true)
            http.onload = () => {
              loadedLibs[lib] = http.responseText
              if (++counter == Object.keys(libs).length) startScripts()
            }
            http.send()
          }
          
          const startScripts = function() {
            for (var lib in libs) eval(loadedLibs[lib])
            console.log("allLoaded")
          }
          
          for (var lib in libs) loadAsync(lib)
          

          简而言之,它会异步加载所有脚本,然后执行它们。

          Github 仓库https://github.com/mudroljub/js-async-loader

          【讨论】:

          【解决方案6】:

          这是一个很好的当代异步脚本加载解决方案,尽管它只使用 async false 处理 js 脚本。

          www.html5rocks.com - Deep dive into the murky waters of script loading 中有一篇很棒的文章。

          在考虑了很多可能的解决方案后,作者得出结论,将js脚本添加到body元素的末尾是避免js脚本阻塞页面渲染的最佳方法。

          同时,作者为那些迫切需要异步加载和执行脚本的人添加了另一个很好的替代解决方案。

          考虑到您有四个名为 script1.js, script2.js, script3.js, script4.js 的脚本,那么您可以使用 应用 async = false

          [
            'script1.js',
            'script2.js',
            'script3.js',
            'script4.js'
          ].forEach(function(src) {
            var script = document.createElement('script');
            script.src = src;
            script.async = false;
            document.head.appendChild(script);
          });
          

          现在,规范说:一起下载,全部下载后按顺序执行。

          Firefox 我不知道这个“异步”的东西是什么,但碰巧我按照添加的顺序执行通过 JS 添加的脚本。 p>

          Safari 5.0 说:我理解“异步”,但不理解用 JS 将其设置为“false”。我会在脚本落地后立即执行你的脚本,无论顺序如何。

          IE 不知道“异步”,但有一个使用“onreadystatechange”的解决方法。

          其他一切都在说:我是你的朋友,我们会照章办事。

          现在,使用 IE

          var scripts = [
            'script1.js',
            'script2.js',
            'script3.js',
            'script4.js'
          ];
          var src;
          var script;
          var pendingScripts = [];
          var firstScript = document.scripts[0];
          
          // Watch scripts load in IE
          function stateChange() {
            // Execute as many scripts in order as we can
            var pendingScript;
            while (pendingScripts[0] && ( pendingScripts[0].readyState == 'loaded' || pendingScripts[0].readyState == 'complete' ) ) {
              pendingScript = pendingScripts.shift();
              // avoid future loading events from this script (eg, if src changes)
              pendingScript.onreadystatechange = null;
              // can't just appendChild, old IE bug if element isn't closed
              firstScript.parentNode.insertBefore(pendingScript, firstScript);
            }
          }
          
          // loop through our script urls
          while (src = scripts.shift()) {
            if ('async' in firstScript) { // modern browsers
              script = document.createElement('script');
              script.async = false;
              script.src = src;
              document.head.appendChild(script);
            }
            else if (firstScript.readyState) { // IE<10
              // create a script and add it to our todo pile
              script = document.createElement('script');
              pendingScripts.push(script);
              // listen for state changes
              script.onreadystatechange = stateChange;
              // must set src AFTER adding onreadystatechange listener
              // else we’ll miss the loaded event for cached scripts
              script.src = src;
            }
            else { // fall back to defer
              document.write('<script src="' + src + '" defer></'+'script>');
            }
          }
          

          【讨论】:

            【解决方案7】:

            您是否考虑过使用 Fetch 注入?我推出了一个名为fetch-inject 的开源库来处理此类情况。以下是您的加载器使用 lib 时的样子:

            fetcInject([
              'js/jquery-1.6.2.min.js',
              'js/marquee.js',
              'css/marquee.css',
              'css/custom-theme/jquery-ui-1.8.16.custom.css',
              'css/main.css'
            ]).then(() => {
              'js/jquery-ui-1.8.16.custom.min.js',
              'js/farinspace/jquery.imgpreload.min.js'
            })
            

            为了向后兼容,利用功能检测并回退到 XHR 注入或脚本 DOM 元素,或者使用 document.write 将标签内联到页面中。

            【讨论】:

              【解决方案8】:

              异步加载的几种解决方案:

              //this function will work cross-browser for loading scripts asynchronously
              function loadScript(src, callback)
              {
                var s,
                    r,
                    t;
                r = false;
                s = document.createElement('script');
                s.type = 'text/javascript';
                s.src = src;
                s.onload = s.onreadystatechange = function() {
                  //console.log( this.readyState ); //uncomment this line to see which ready states are called.
                  if ( !r && (!this.readyState || this.readyState == 'complete') )
                  {
                    r = true;
                    callback();
                  }
                };
                t = document.getElementsByTagName('script')[0];
                t.parentNode.insertBefore(s, t);
              }
              

              如果您已经在页面上安装了 jQuery,只需使用:

              $.getScript(url, successCallback)*

              此外,您的脚本可能会在文档加载完成之前被加载/执行,这意味着您需要等待 document.ready 才能将事件绑定到元素。

              不看代码就无法具体说明问题所在。

              最简单的解决方案是将所有脚本内嵌在页面底部,这样它们就不会在执行时阻止 HTML 内容的加载。它还避免了必须异步加载每个所需脚本的问题。

              如果您有一个并不总是使用的特别花哨的交互,需要某种更大的脚本,那么避免在需要之前加载该特定脚本(延迟加载)可能很有用。

              * scripts loaded with $.getScript will likely not be cached


              对于可以使用Promise 对象等现代功能的任何人来说,loadScript 函数已经变得非常简单:

              function loadScript(src) {
                  return new Promise(function (resolve, reject) {
                      var s;
                      s = document.createElement('script');
                      s.src = src;
                      s.onload = resolve;
                      s.onerror = reject;
                      document.head.appendChild(s);
                  });
              }
              

              请注意,此版本不再接受 callback 参数,因为返回的 Promise 将处理回调。以前是 loadScript(src, callback) 现在是 loadScript(src).then(callback)

              这具有能够检测和处理故障的额外好处,例如可以调用...

              loadScript(cdnSource)
                  .catch(loadScript.bind(null, localSource))
                  .then(successCallback, failureCallback);
              

              ...它会优雅地处理 CDN 中断。

              【讨论】:

              • 我即将开始尝试。但是,如果我在将页面重定向到不同页面时将这些脚本加载到不同的页面上,并且该页面恰好具有相同的脚本,则它们不应该花费时间来加载。它们应该在缓存中吗?那么我不应该实施该技术吗?
              • 我改变了孩子并将其附加到头部标签而不是身体...... ..var x = document.getElementsByTagName('head')[0]; x.appendChild(s);
              • @TonoNam,您可以只使用document.head.appendChild,但是将脚本添加到&lt;head&gt; 存在一些小众问题;没有什么会阻止脚本加载和执行。
              • 我必须使用 t.parentNode.insertBefore(而不是 t.parent)。
              • @MuhammadUmer,如果您在文档加载之前使用document.write 编写附加脚本标签,该脚本将作为加载页面的一部分同步执行,并且不会包含任何异步回调自己的行为。如果您正在创建脚本元素并将其添加到页面,那么您将有权添加事件侦听器以异步触发。 tl;dr: 这取决于您如何使用 JS 加载脚本。
              【解决方案9】:

              几个注意事项:

              • s.async = true 对于 HTML5 doctype 不是很正确,正确的是 s.async = 'async'(实际上使用 true 是正确的,感谢 amn 在下面的 comment 中指出)
              • 使用超时来控制顺序不是很好也不安全,而且你还让加载时间变大了,等于所有超时的总和!

              由于最近有一个异步加载文件的原因,但是为了按顺序,我建议在您的示例中采用更多功能驱动的方式(删除 console.log 以供生产使用:)):

              (function() {
                  var prot = ("https:"===document.location.protocol?"https://":"http://");
              
                  var scripts = [
                      "path/to/first.js",
                      "path/to/second.js",
                      "path/to/third.js"
                  ];
              
                  function completed() { console.log('completed'); }  // FIXME: remove logs
              
                  function checkStateAndCall(path, callback) {
                      var _success = false;
                      return function() {
                          if (!_success && (!this.readyState || (this.readyState == 'complete'))) {
                              _success = true;
                              console.log(path, 'is ready'); // FIXME: remove logs
                              callback();
                          }
                      };
                  }
              
                  function asyncLoadScripts(files) {
                      function loadNext() { // chain element
                          if (!files.length) completed();
                          var path = files.shift();
                          var scriptElm = document.createElement('script');
                          scriptElm.type = 'text/javascript';
                          scriptElm.async = true;
                          scriptElm.src = prot+path;
                          scriptElm.onload = scriptElm.onreadystatechange = \
                              checkStateAndCall(path, loadNext); // load next file in chain when
                                                                 // this one will be ready 
                          var headElm = document.head || document.getElementsByTagName('head')[0];
                          headElm.appendChild(scriptElm);
                      }
                      loadNext(); // start a chain
                  }
              
                  asyncLoadScripts(scripts);
              })();
              

              【讨论】:

              • s.async = true正确async 属性在 W3C 的 HTML 5 建议 w3.org/TR/html5/scripting-1.html#attr-script-async 中明确指定为布尔值。您将async 属性 与实现HTMLScriptElement DOM 接口的对象公开的async 属性混淆了。事实上,当通过Element.setAttribute 之类的方式操作元素的相应属性时,您应该使用element.setAttribute("async", "async"),因为所有 HTML 属性首先是文本。
              • “由于最近有一个异步加载文件的原因,但为了按顺序,我建议在您的示例中采用更多功能驱动的方式 [...]”。我知道异步通常“更好”,但你指的是什么“最近”的原因?
              • 我改变了 'if (!files.length) completed();'添加一个'return':'if (!files.length) {completed();返回;}'
              【解决方案10】:

              感谢 HTML5,您现在可以通过在标签中添加“async”来声明要异步加载的脚本:

              <script async>...</script>
              

              注意:async 属性仅适用于外部脚本(并且仅应在存在 src 属性时使用)。

              注意:可以通过多种方式执行外部脚本:

              • 如果存在异步:脚本与页面的其余部分异步执行(脚本将在页面继续解析时执行)
              • 如果 async 不存在而 defer 存在:脚本在页面完成解析后执行
              • 如果 async 或 defer 都不存在:在浏览器继续解析页面之前立即获取并执行脚本

              看到这个:http://www.w3schools.com/tags/att_script_async.asp

              【讨论】:

                【解决方案11】:

                您可以使用LABJSRequreJS

                LABJSRequireJS 等脚本加载器将提高代码的速度和质量。

                【讨论】:

                  【解决方案12】:

                  看看这个https://github.com/stephen-lazarionok/async-resource-loader。它有一个示例,展示了如何一次加载 JS、CSS 和多个文件。

                  【讨论】:

                  • 可以稍微改变一下以摆脱jquery依赖
                  【解决方案13】:

                  来自谷歌的例子

                  <script type="text/javascript">
                    (function() {
                      var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
                      po.src = 'https://apis.google.com/js/plusone.js?onload=onLoadCallback';
                      var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
                    })();
                  </script>
                  

                  【讨论】:

                    【解决方案14】:

                    HTML5 的新 'async' 属性应该可以解决问题。如果您关心 IE,大多数浏览器也支持“延迟”。

                    异步 ​​- HTML

                    <script async src="siteScript.js" onload="myInit()"></script>
                    

                    defer - HTML

                    <script defer src="siteScript.js" onload="myInit()"></script>
                    

                    在分析新的 Adsense 广告单元代码时,我注意到了该属性,然后搜索将我带到了这里:http://davidwalsh.name/html5-async

                    【讨论】:

                    • 在阅读stackoverflow.com/questions/2774373/…后我的理解是,asyn不是为了加载,而是为了确定何时运行包含的javascript。
                    • defer 属性使浏览器延迟脚本的执行,直到文档被加载和解析并准备好被操作。 async 属性使浏览器尽快运行脚本,但在下载脚本时不会阻止文档解析
                    • "asyn 不是用来加载的,而是用来决定什么时候运行包含的javascript" 这并不矛盾;在所有情况下,浏览器都会尽快开始加载脚本。但是没有 asyncdefer 它会在加载时阻止渲染。设置async 将告诉它不要阻止并尽快运行脚本。设置defer 将告诉它不要阻塞,而是等待running脚本直到页面完成。通常只要脚本没有任何依赖项(例如 jQuery),尽快运行脚本是没有问题的。如果一个脚本依赖于另一个脚本,请使用onLoad 等待它。
                    • @StijndeWitt 如果既没有指定异步也没有指定延迟怎么办?
                    • @MohammedShareefC 如果你都没有指定,你会得到与同步行为非常相似的东西;浏览器在下载和运行脚本时会阻止进一步的处理。因此,有效的默认行为是同步。但是因为这对性能不利,所以浏览器会尽可能多地解决它。他们可以继续解析、加载和应用 CSS 等……但是他们不能开始运行下一个脚本片段。所以东西会阻塞。通过设置异步,您是在告诉浏览器可以继续操作,并且您将确保自己让它工作。
                    【解决方案15】:

                    我会通过检查是否存在回调并允许传递参数来完成 zzzzBov 的回答:

                        function loadScript(src, callback, args) {
                          var s, r, t;
                          r = false;
                          s = document.createElement('script');
                          s.type = 'text/javascript';
                          s.src = src;
                          if (typeof(callback) === 'function') {
                            s.onload = s.onreadystatechange = function() {
                              if (!r && (!this.readyState || this.readyState === 'complete')) {
                                r = true;
                                callback.apply(args);
                              }
                            };
                          };
                          t = document.getElementsByTagName('script')[0];
                          t.parent.insertBefore(s, t);
                        }
                    

                    【讨论】:

                      【解决方案16】:

                      当完成加载的所有脚本将页面重定向到 index2.html 时,我异步加载了脚本(html 5 具有该功能),其中 index2.html 使用相同的库。因为一旦页面重定向到 index2.html,浏览器就有缓存,index2.html 会在不到一秒的时间内加载,因为它拥有加载页面所需的一切。在我的 index.html 页面中,我还加载了我计划使用的图像,以便浏览器将这些图像放在缓存中。所以我的 index.html 看起来像:

                      <!DOCTYPE html>
                      <html>
                      <head>
                          <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
                          <title>Project Management</title>
                      
                          <!-- the purpose of this page is to load all the scripts on the browsers cache so that pages can load fast from now on -->
                      
                          <script type="text/javascript">
                      
                              function stylesheet(url) {
                                  var s = document.createElement('link');
                                  s.type = 'text/css';
                                  s.async = true;
                                  s.src = url;
                                  var x = document.getElementsByTagName('head')[0];
                                  x.appendChild(s);
                              }
                      
                              function script(url) {
                                  var s = document.createElement('script');
                                  s.type = 'text/javascript';
                                  s.async = true;
                                  s.src = url;
                                  var x = document.getElementsByTagName('head')[0];
                                  x.appendChild(s);
                              }
                      
                              //load scritps to the catche of browser
                              (function () {            
                                      stylesheet('css/custom-theme/jquery-ui-1.8.16.custom.css');
                                      stylesheet('css/main.css');
                                      stylesheet('css/marquee.css');
                                      stylesheet('css/mainTable.css');
                      
                                      script('js/jquery-ui-1.8.16.custom.min.js');
                                      script('js/jquery-1.6.2.min.js');
                                      script('js/myFunctions.js');
                                      script('js/farinspace/jquery.imgpreload.min.js');
                                      script('js/marquee.js');            
                              })();
                      
                          </script>
                      
                          <script type="text/javascript">
                             // once the page is loaded go to index2.html
                              window.onload = function () {
                                  document.location = "index2.html";
                              }
                          </script>
                      
                      </head>
                      <body>
                      
                      <div id="cover" style="position:fixed; left:0px; top:0px; width:100%; height:100%; background-color:Black; z-index:100;">Loading</div>
                      
                      <img src="images/home/background.png" />
                      <img src="images/home/3.png"/>
                      <img src="images/home/6.jpg"/>
                      <img src="images/home/4.png"/>
                      <img src="images/home/5.png"/>
                      <img src="images/home/8.jpg"/>
                      <img src="images/home/9.jpg"/>
                      <img src="images/logo.png"/>
                      <img src="images/logo.png"/>
                      <img src="images/theme/contentBorder.png"/>
                      
                      </body>
                      </html>
                      

                      另一个好处是我可以在页面中放置一个加载器,当页面加载完成时,加载器将消失,并在几毫秒内运行新页面。

                      【讨论】:

                      • @MohammedShareefC 具有讽刺意味。仅用于预加载内容的特殊页面听起来不是 SEO 明智的好主意。预加载很棒,但您不需要重定向来实现它。只需将链接粘贴在隐藏的 div 中,浏览器就会自动为您处理。然后不要重定向,而只是呈现实际页面。 复制粘贴阅读此内容:请在使用任何 HTML 之前将 ISO-88591 编码更改为 UTF-8,以便我们其他人可以很快摆脱编码地狱。谢谢!
                      【解决方案17】:

                      我建议你看看Modernizr。它是一个小型轻量级库,您可以异步加载您的 javascript,其功能允许您检查文件是否已加载并在您指定的其他脚本中执行脚本。

                      这里是一个加载jquery的例子:

                      Modernizr.load([
                        {
                          load: '//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.js',
                          complete: function () {
                            if ( !window.jQuery ) {
                                  Modernizr.load('js/libs/jquery-1.6.1.min.js');
                            }
                          }
                        },
                        {
                          // This will wait for the fallback to load and
                          // execute if it needs to.
                          load: 'needs-jQuery.js'
                        }
                      ]);
                      

                      【讨论】:

                        【解决方案18】:

                        脚本加载速度如此缓慢的一个原因是,如果您在加载页面时正在运行所有脚本,如下所示:

                        callMyFunctions();
                        

                        代替:

                        $(window).load(function() {
                              callMyFunctions();
                        });
                        

                        这第二段脚本会等到浏览器完全加载完所有 Javascript 代码后,才会开始执行任何脚本,让用户觉得页面加载得更快了。

                        如果您希望通过减少加载时间来增强用户体验,我不会选择“加载屏幕”选项。在我看来,这比让页面加载更慢更烦人。

                        【讨论】:

                          【解决方案19】:

                          好吧,x.parentNode 返回 HEAD 元素,因此您将脚本插入到 head 标记之前。也许这就是问题所在。

                          改用x.parentNode.appendChild()

                          【讨论】:

                            【解决方案20】:

                            我建议先考虑缩小文件,看看这是否能给你带来足够大的速度提升。如果您的主机速度很慢,可以尝试将静态内容放在 CDN 上。

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 2016-07-09
                              • 2012-10-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2016-03-26
                              • 2019-06-29
                              • 1970-01-01
                              相关资源
                              最近更新 更多