Можно ли отложить загрузку jQuery? - PullRequest
65 голосов
/ 02 мая 2011

Посмотрим правде в глаза, jQuery / jQuery-ui - это тяжелая загрузка.

Google рекомендует отложенная загрузка JavaScript для ускорения начального рендеринга.Моя страница использует jQuery для настройки некоторых вкладок, которые расположены низко на странице (в основном вне начального вида), и я хотел бы отложить jQuery до ПОСЛЕ отображения страницы.

Код отсрочки Google добавляет тегв DOM после загрузки страницы путем подключения к событию onLoad тела:

<script type="text/javascript">

 // Add a script element as a child of the body
 function downloadJSAtOnload() {
 var element = document.createElement("script");
 element.src = "deferredfunctions.js";
 document.body.appendChild(element);
 }

 // Check for browser support of event handling capability
 if (window.addEventListener)
 window.addEventListener("load", downloadJSAtOnload, false);
 else if (window.attachEvent)
 window.attachEvent("onload", downloadJSAtOnload);
 else window.onload = downloadJSAtOnload;

</script>

Я бы хотел отложить загрузку jQuery таким образом, но когда я попробовал это, мой код jQuery не смог найти jQuery (несовершенно неожиданно с моей стороны):

$(document).ready(function() {
    $("#tabs").tabs();
});

Так что, похоже, мне нужно найти способ отложить выполнение моего кода jQuery до загрузки jQuery.Как определить, что добавленный тег завершил загрузку и анализ?

Как следствие, представляется, что асинхронная загрузка также может содержать ответ.

Есть мысли?

Ответы [ 15 ]

51 голосов
/ 02 мая 2011

Попробуйте, это то, что я редактировал некоторое время назад из букмарклета jQuerify. Я часто использую его для загрузки jQuery и выполнения вещей после загрузки. Вы, конечно, можете заменить URL-адрес там своим собственным URL-адресом к вашему настроенному jquery.

(function() {
      function getScript(url,success){
        var script=document.createElement('script');
        script.src=url;
        var head=document.getElementsByTagName('head')[0],
            done=false;
        script.onload=script.onreadystatechange = function(){
          if ( !done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') ) {
            done=true;
            success();
            script.onload = script.onreadystatechange = null;
            head.removeChild(script);
          }
        };
        head.appendChild(script);
      }
        getScript('http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js',function(){
            // YOUR CODE GOES HERE AND IS EXECUTED AFTER JQUERY LOADS
        });
    })();

Я бы действительно объединил jQuery и jQuery-UI в один файл и использовал бы URL для него. Если вы ДЕЙСТВИТЕЛЬНО хотели загрузить их отдельно, просто соедините getScripts:

getScript('http://myurltojquery.js',function(){
        getScript('http://myurltojqueryUI.js',function(){
              //your tab code here
        })
});
13 голосов
/ 23 августа 2013

Поскольку это вопрос высшего ранга по важной теме, позвольте мне быть настолько смелым, чтобы высказать свое мнение по этому вопросу, основываясь на предыдущем ответе @valmarv и @ amparsand.

Я использую мульти-массивный массив для загрузки скриптов.Группируя те, у которых нет зависимостей между ними:

var dfLoadStatus = 0;
var dfLoadFiles = [
      ["http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"],
      ["http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js",
       "/js/somespecial.js",
       "/js/feedback-widget.js#2312195",
       "/js/nohover.js"]
     ];

function downloadJSAtOnload() {
    if (!dfLoadFiles.length) return;

    var dfGroup = dfLoadFiles.shift();
    dfLoadStatus = 0;

    for(var i = 0; i<dfGroup.length; i++) {
        dfLoadStatus++;
        var element = document.createElement('script');
        element.src = dfGroup[i];
        element.onload = element.onreadystatechange = function() {
        if ( ! this.readyState || 
               this.readyState == 'complete') {
            dfLoadStatus--;
            if (dfLoadStatus==0) downloadJSAtOnload();
        }
    };
    document.body.appendChild(element);
  }

}

if (window.addEventListener)
    window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
    window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;

Он загружает первый jquery после загрузки и продолжает загружать другие скрипты сразу.Вы можете легко добавлять скрипты, добавляя в массив в любом месте вашей страницы:

dfLoadFiles.push(["/js/loadbeforeA.js"]);
dfLoadFiles.push(["/js/javascriptA.js", "/js/javascriptB.js"]);
dfLoadFiles.push(["/js/loadafterB.js"]);
8 голосов
/ 31 января 2017

Вот хорошее описание современного подхода для асинхронной / отложенной загрузки javascript .Но это не работает для встроенных скриптов

<script type="text/javascript" src="/jquery/3.1.1-1/jquery.min.js" defer></script>
<script type="text/javascript" defer>
    $(function () {   //  <- jquery is not yet initialized
      ...
    });
</script>

Самое простое решение для асинхронной загрузки было предложено @nilskp - скрипт externalize:

<script type="text/javascript" src="/jquery/3.1.1-1/jquery.min.js" defer></script>
<script type="text/javascript" src="resources/js/onload.js" defer></script>
3 голосов
/ 02 мая 2011
element.addEventListener("load", function () {
    $('#tabs').tabs()
}, false);

Попробуйте это.

3 голосов
/ 02 мая 2011

Поместите jQuery и ваш зависимый от jQuery код в конец вашего HTML-файла.

Редактировать: немного яснее

<html>
<head></head>
<body>
    <!-- Your normal content here -->
    <script type="text/javascript" src="http://path/to/jquery/jquery.min.js"></script>
    <script>//Put your jQuery code here</script>
</body>
</html>
2 голосов
/ 19 ноября 2013

В определенных ситуациях вы можете вызвать событие при загрузке jquery.

<script type="text/javascript">
    (function (window) {

        window.jQueryHasLoaded = false;

        document.body.addEventListener('jqueryloaded', function (e) {
            console.log('jqueryloaded ' + new Date() );
        }, false);

        function appendScript(script) {
            var tagS = document.createElement("script"), 
                s = document.getElementsByTagName("script")[0];
            tagS.src = script.src;
            s.parentNode.insertBefore(tagS, s);

            if ( script.id == 'jquery' ) {
                tagS.addEventListener('load', function (e) {
                    window.jQueryHasLoaded = true;
                    var jQueryLoaded = new Event('jqueryloaded');
                    document.body.dispatchEvent(jQueryLoaded);
                }, false);
            }
        }

        var scripts = [
            {
                'id': 'jquery',
                'src': 'js/libs/jquery/jquery-2.0.3.min.js'
            },
            {
                'src': 'js/myscript1.js'
            },
            {
                'src': 'js/myscript2.js'
            }
        ];

        for (var i=0; i < scripts.length; i++) {
            appendScript(scripts[i]);
        }

    }(window));
</script>

Затем оберните ваши зависимости в функцию:

// myscript1.js 
(function(){ 

    function initMyjQueryDependency() {
        console.log('my code is executed after jquery is loaded!');
        // here my code that depends on jquery
    }

    if ( jQueryHasLoaded === true )
        initMyjQueryDependency();
    else
        document.body.addEventListener('jqueryloaded', initMyjQueryDependency, false);

}());

Если jquery завершает загрузку после других сценариев, ваши зависимости будут выполняться при возникновении события jqueryloaded.

Если jquery уже загружен, jQueryHasLoaded === true, ваша зависимость будет выполнена initMyjQueryDependency().

1 голос
/ 18 декабря 2014

Я думаю, что здесь стоит упомянуть Modernizr.load () - он прекрасно справляется с загрузкой зависимостей

1 голос
/ 15 октября 2013
<!doctype html>
<html>
    <head>

    </head>
    <body>
        <p>If you click on the "Hide" button, I will disappear.</p>
        <button id="hide" >Hide</button>
        <button id="show" >Show</button>

        <script type="text/javascript">
            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.body.appendChild(script);
            }
            loadScript("http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js",
                    function() {
                        //YAHOO.namespace("mystuff");
                        $("#show").click(function() {
                            $("p").show();
                        });
                        $("#hide").click(function() {
                            $("p").hide();
                        });

                        //more...
                    });
        </script>

    </body>
</html>
1 голос
/ 25 сентября 2012

Вот моя версия, которая поддерживает связывание, чтобы убедиться, что скрипты загружаются один за другим, на основе кода ampersand :

var deferredJSFiles = ['jquery/jquery', 'file1', 'file2', 'file3'];
function downloadJSAtOnload() {
    if (!deferredJSFiles.length)
        return;
    var deferredJSFile = deferredJSFiles.shift();
    var element = document.createElement('script');
    element.src = deferredJSFile.indexOf('http') == 0 ? deferredJSFile : '/js/' + deferredJSFile + '.js';
    element.onload = element.onreadystatechange = function() {
        if (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')
            downloadJSAtOnload();
    };
    document.body.appendChild(element);
}
if (window.addEventListener)
    window.addEventListener('load', downloadJSAtOnload, false);
else if (window.attachEvent)
    window.attachEvent('onload', downloadJSAtOnload);
else
    window.onload = downloadJSAtOnload;
1 голос
/ 02 мая 2011

Мне кажется, все, что вам нужно сделать, это либо а) добавить код jQuery, который вы хотите запустить при загрузке, в конец файла jQuery, либо б) добавить его к функции downloadJSAtOnload следующим образом:

<script type="text/javascript">

 // Add a script element as a child of the body
 function downloadJSAtOnload() {
 var element = document.createElement("script");
 element.src = "deferredfunctions.js";
 document.body.appendChild(element);
 $("#tabs").tabs(); // <==== NOTE THIS. This should theoretically run after the
                    // script has been appended, though you'll have to test this
                    // because I don't know if the JavaScript above will wait for
                    // the script to load before continuing
 }

 // Check for browser support of event handling capability
 if (window.addEventListener)
 window.addEventListener("load", downloadJSAtOnload, false);
 else if (window.attachEvent)
 window.attachEvent("onload", downloadJSAtOnload);
 else window.onload = downloadJSAtOnload;

</script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...