Можно отложить загрузку jQuery?
Посмотрим правде в глаза, 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. Как определить, что добавленный тег завершил загрузку и разбор?
Как следствие, похоже, что азартная загрузка также может содержать ответ.
Любые мысли?
Ответы
Ответ 1
Попробуйте это, что-то, что я редактировал некоторое время назад из jQuerify bookmarklet. Я часто использую его для загрузки 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
})
});
Ответ 2
Поскольку это вопрос с высоким рейтингом по важному вопросу, позвольте мне быть настолько смелым, чтобы обеспечить его собственный подход к этому, основываясь на предыдущем ответе от @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"]);
Ответ 3
Поместите 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>
Ответ 4
element.addEventListener("load", function () {
$('#tabs').tabs()
}, false);
Попробуйте это.
Ответ 5
В определенной ситуации вы можете запустить событие при загрузке 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()
.
Ответ 6
Вот хорошее описание современного подхода для загрузки javascript для async/defer. Но это не работает для встроенных скриптов
<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:
<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>
Ответ 7
Следующий код должен загружать ваши скрипты после завершения загрузки окна:
<html>
<head>
<script>
var jQueryLoaded = false;
function test() {
var myScript = document.createElement('script');
myScript.type = 'text/javascript';
myScript.async = true;
myScript.src = jQueryLoaded ? 'http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.js' : 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js';
document.body.appendChild(myScript);
if(!jQueryLoaded){
alert('jquery was loaded');
jQueryLoaded = true;
test();
} else {
alert('jqueryui was loaded');
}
}
if (window.addEventListener){
alert('window.addEventListener');
window.addEventListener("load", test, false);
} else if (window.attachEvent){
alert('window.attachEvent');
window.attachEvent("onload", test);
} else{
alert('window.onload');
window.onload = test;
}
</script>
</head>
<body>
<p>Placeholder text goes here</p>
</body>
</html>
Работала для меня в Chrome, FF и IE9 - сообщите мне, помогает ли это
Ответ 8
Ну, мне кажется, все, что вам нужно сделать, это либо: a) добавить код jQuery, который вы хотите запустить при загрузке, в конец файла jQuery или b) добавить его к функции 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>
Ответ 9
Здесь моя версия, которая поддерживает цепочку, чтобы убедиться, что сценарии загружаются один за другим, на основе амперсанда:
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;
Ответ 10
<!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>
Ответ 11
Я думаю, что Modernizr.load() стоит упомянуть здесь - он очень сильно загружает загрузку зависимостей
Ответ 12
Появляется, что вам просто нужно <script defer>
: http://www.w3schools.com/tags/att_script_defer.asp
Ответ 13
Взгляните jQuery.holdReady()
"Удерживает или освобождает выполнение события jQuery ready." (jQuery 1.6 +)
http://api.jquery.com/jQuery.holdReady/
Ответ 14
Я добавляю этот фрагмент кода после тега jquery script async/debfered script, это определяет временную функцию $, которая будет накапливать все, что она должна запускать, когда все будет загружаться, а затем, когда мы закончим использовать $, который к этому времени будет перезаписан для выполнения функций. С этим фрагментом кода нет необходимости менять синтаксис onload jQuery дальше в документе.
<script defer async src="https://code.jquery.com/jquery-2.2.0.min.js">
<script>
var executeLater = [];
function $(func) {
executeLater.push(func);
}
window.addEventListener('load', function () {
$(function () {
for (var c = 0; c < executeLater.length; c++) {
executeLater[c]();
}
});
})
</script>
.... и затем...
<script>
$(function() {
alert("loaded");
});
</script>
Ответ 15
Загрузите все скрипты в конце html с помощью http://labjs.com, это 100% -ное решение, и я много раз его тестировал против правил gtmetrix. пример http://gtmetrix.com/reports/interactio.cz/jxomHSLV