Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 18.02.2018, 17:51
Аватар для Black_Star
Профессор
Отправить личное сообщение для Black_Star Посмотреть профиль Найти все сообщения от Black_Star
 
Регистрация: 11.07.2016
Сообщений: 300

Отложеная загрузка скриптов. Как быть с jQuery ?
Добрый день уважаемые. Вопрос к тем кто занимался вопросами оптимизации и пытается следовать рекомендации Google по вопросу - Удаления кода JavaScript и CSS, блокирующий отображение верхней части страницы . С CSS я худо-бедно разобрался, а вот как быть если необходимо что б первой всегда на страницу подгружалась библиотека с jQuery? Вот я нашёл такую рекомендацию

загружать jQuery по событию load
function dlOnload() {
  var jq = document.createElement("script"), mainScript;
  jq.src = "https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js";
  document.body.appendChild(jq);

  jq.onload = function() {
    mainScript = document.createElement("script");
    mainScript.src = "scripts/main.js";
    document.body.appendChild(mainScript);
  }
}

window.addEventListener("load", dlOnload, false);

а файлы зависимых от jQuery файлов после его загрузки. (Это вроди как main.js) Пока не удалось запустить данный скрипт. Да и как быть если этих дополнительных много... + если идет в середине php файла какой-то AJAX запрос и ему нужен jQuery
Ответить с цитированием
  #2 (permalink)  
Старый 18.02.2018, 17:53
Аватар для j0hnik
Профессор
Отправить личное сообщение для j0hnik Посмотреть профиль Найти все сообщения от j0hnik
 
Регистрация: 01.12.2016
Сообщений: 3,650

Советую не заморачиваться с этим!
особенно если JQ как то влияет на формирование начальной видимой части (тоесть первые 1080px шапка и часть основного контента) это тоже рекомендация поисковиков

Последний раз редактировалось j0hnik, 18.02.2018 в 17:56.
Ответить с цитированием
  #3 (permalink)  
Старый 18.02.2018, 19:45
Аватар для Белый шум
Профессор
Отправить личное сообщение для Белый шум Посмотреть профиль Найти все сообщения от Белый шум
 
Регистрация: 19.01.2012
Сообщений: 505

Black_Star, у меня есть полностью рабочее решение:

Где-то в инете нашёл скрипт jQl и немного его поменял (уже не помню где и что именно менял):
var jQl={q:[],dq:[],gs:[],ready:function(a){"function"==typeof a&&jQl.q.push(a);return jQl},getScript:function(a,c){jQl.gs.push([a,c])},unq:function(){for(var a=0;a<jQl.q.length;a++) $(document).ready(jQl.q[a]);jQl.q=[]},ungs:function(){for(var a=0;a<jQl.gs.length;a++)jQuery.getScript(jQl.gs[a][0],jQl.gs[a][1]);jQl.gs=[]},bId:null,
	boot:function(a){"undefined"==typeof window.jQuery.fn?jQl.bId||(jQl.bId=setInterval(function(){
	 jQl.boot(a)},25)):(jQl.bId&&clearInterval(jQl.bId),jQl.bId=0,jQl.unqjQdep(),jQl.ungs(),jQuery(jQl.unq()), "function"==typeof a&&a())
	},booted:function(){return 0===jQl.bId},loadjQ:function(a,c){setTimeout(function(){var b=document.createElement("script");b.src=a;document.getElementsByTagName("head")[0].appendChild(b)},1);jQl.boot(c)},loadjQdep:function(a){jQl.loadxhr(a,jQl.qdep)},qdep:function(a){a&&("undefined"!==typeof window.jQuery.fn&&!jQl.dq.length?jQl.rs(a):jQl.dq.push(a))},unqjQdep:function(){if("undefined"==typeof window.jQuery.fn)setTimeout(jQl.unqjQdep,50);else{for(var a=0;a<jQl.dq.length;a++)jQl.rs(jQl.dq[a]); jQl.dq=[]}},rs:function(a){var c=document.createElement("script");document.getElementsByTagName("head")[0].appendChild(c);c.text=a},loadxhr:function(a,c){var b;b=jQl.getxo();b.onreadystatechange=function(){4!=b.readyState||200!=b.status||c(b.responseText,a)};try{b.open("GET",a,!0),b.send("")}catch(d){}},getxo:function(){var a=!1;try{a=new XMLHttpRequest}catch(c){for(var b=["MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"],d=0;d<b.length;++d){try{a= new ActiveXObject(b[d])}catch(e){continue}break}}finally{return a}}};if("undefined"==typeof window.jQuery){var $=jQl.ready,jQuery=$;$.getScript=jQl.getScript};

Данный код создаёт 3 массива (для $(document).ready(), для $.getScript и для собственной ф-ии jQl.loadjQdep() - она асинхронно загружает внешний скрипт сразу, не дожидаясь когда загрузится jQuery (но выпонит его лишь после загрузки jQuery)).

Вставляем этот код в head на каждой странице. Затем закидываем код jQuery и всё что от него зависит в один js файл, в самом конце кода вставляем строку:
jQl.boot();

которая инициирует выполнение кода из массивов (фактически, просто вызывает эти же ф-ии в том же порядке, а поскольку они на этот момент уже переопределены кодом jQuery, то будут выполнены им, за исключением 3-го массива).

Получившийся единый js-файл подгружаем асинхронно (обязательно _после_ кода jQl):
<script async type="text/javascript" src="/js/combined.min.js?v1"></script>


Соответственно, весь js-код на странице, который зависит от скриптов из combined.min.js надо обернуть в $(document).ready(function(){ ... }); либо в короткий вариант того же самого: $(function(){ ... });

Если же внешний файл, зависимый от jQuery нельзя поместить в общий js-файл (например он большой, но нужен не на всех страницах), то загружаем его через jQl.loadjQdep('/path/to/file.js');
Но для каждого такого скрипта надо соблюсти очерёдность исполнения inline-кода - для этого используем deffered:
1) В конце общего js-файла (но перед строкой jQl.boot();) определяем переменную-индикатор, например для скрипта lazyload:
$lazyload = $.Deferred();

2) В конце файла отдельного скрипта ставим резолв этой переменной:
$lazyload.resolve();

3) Весь inline-код на странице, зависимый от этого скрипта, помещаем в блок, который гарантирует что он выполнится только после резолва:
$(function(){  $lazyload.done(function(){ ... });  });



P.S.: в процессе эксплуатации выяснилось, что в сафари событие DOMContentLoaded не запускает ф-ии, которые начали слушать это событие после того как оно уже сработало, поэтому иногда весь jQuery-зависимый inline-код не срабатывает (если общий файл с кодом jQuery загрузился после основной страницы). Для обхода этого добавили небольшой хак, и общее решение теперь выглядит так:

В <head> каждой страницы такой код:
<input id="workaround-DOMContentLoaded-event" type="hidden" value="0" />
<script>
	var jQl={q:[],dq:[],gs:[],ready:function(a){"function"==typeof a&&jQl.q.push(a);return jQl},getScript:function(a,c){jQl.gs.push([a,c])},unq:function(){for(var a=0;a<jQl.q.length;a++) $(document).ready(jQl.q[a]);jQl.q=[]},ungs:function(){for(var a=0;a<jQl.gs.length;a++)jQuery.getScript(jQl.gs[a][0],jQl.gs[a][1]);jQl.gs=[]},bId:null,
	boot:function(a){"undefined"==typeof window.jQuery.fn?jQl.bId||(jQl.bId=setInterval(function(){
	 jQl.boot(a)},25)):(jQl.bId&&clearInterval(jQl.bId),jQl.bId=0,jQl.unqjQdep(),jQl.ungs(),jQuery(jQl.unq()), "function"==typeof a&&a())
	},booted:function(){return 0===jQl.bId},loadjQ:function(a,c){setTimeout(function(){var b=document.createElement("script");b.src=a;document.getElementsByTagName("head")[0].appendChild(b)},1);jQl.boot(c)},loadjQdep:function(a){jQl.loadxhr(a,jQl.qdep)},qdep:function(a){a&&("undefined"!==typeof window.jQuery.fn&&!jQl.dq.length?jQl.rs(a):jQl.dq.push(a))},unqjQdep:function(){if("undefined"==typeof window.jQuery.fn)setTimeout(jQl.unqjQdep,50);else{for(var a=0;a<jQl.dq.length;a++)jQl.rs(jQl.dq[a]); jQl.dq=[]}},rs:function(a){var c=document.createElement("script");document.getElementsByTagName("head")[0].appendChild(c);c.text=a},loadxhr:function(a,c){var b;b=jQl.getxo();b.onreadystatechange=function(){4!=b.readyState||200!=b.status||c(b.responseText,a)};try{b.open("GET",a,!0),b.send("")}catch(d){}},getxo:function(){var a=!1;try{a=new XMLHttpRequest}catch(c){for(var b=["MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"],d=0;d<b.length;++d){try{a= new ActiveXObject(b[d])}catch(e){continue}break}}finally{return a}}};if("undefined"==typeof window.jQuery){var $=jQl.ready,jQuery=$;$.getScript=jQl.getScript};

	document.addEventListener('DOMContentLoaded', function(){
		var i = document.getElementById('workaround-DOMContentLoaded-event');
		i.value = 1;
		i.click();
	});
</script>
<script async type="text/javascript" src="/js/combined.min.js?v1"></script>


А в конце файла combined.min.js такой код:
jQl.boot();

$('#workaround-DOMContentLoaded-event').on('click', function(){
	if( this.value != 1 ) return;
	jQuery.ready();
	$(this).remove();
}).trigger('click');
Ответить с цитированием
  #4 (permalink)  
Старый 18.02.2018, 20:53
Аватар для Black_Star
Профессор
Отправить личное сообщение для Black_Star Посмотреть профиль Найти все сообщения от Black_Star
 
Регистрация: 11.07.2016
Сообщений: 300

Сообщение от Белый шум
Белый шум
Спасибо, это больше похоже на то что я ищу. Хотя с первого прочтения как-то слабовато вник Остался такой невыясненный момент когда у меня в проекте встречается встроенный в php страницу тег script в котором выполняется скажем некий AJAX запрос с использованием всё того же jQuery. Сработает ли предложенный метод в данном случае? Ведь насколько я понял все скрипты в данном методе являются Внешне подключаемыми?
Ответить с цитированием
  #5 (permalink)  
Старый 18.02.2018, 21:03
Аватар для Белый шум
Профессор
Отправить личное сообщение для Белый шум Посмотреть профиль Найти все сообщения от Белый шум
 
Регистрация: 19.01.2012
Сообщений: 505

Сообщение от Black_Star
Сработает ли предложенный метод в данном случае?
Сработает. Обернёте этот код в $(function(){ ... }); <-- вместо многоточий ваш код
и он отработает после того как выполнятся оба условия:
1) браузер сформировал DOM страницы;
2) основной внешний скрипт с библиотекой jQuery загрузился и выполнился.

P.S.: скорей всего бОльшая часть jQuery-зависимого кода у вас уже обёрнута таким образом, поэтому второй раз оборачивать не нужно.

Последний раз редактировалось Белый шум, 18.02.2018 в 21:07.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как установить дефотлтное значение в jquery autocomplette? heksen jQuery 1 28.02.2015 17:24
Как быть, Jquery не отрабатывает под Opera Mobile? free_style jQuery 2 04.09.2014 12:49
Как получить в JQUERY каждую строку как отдельный объект? Alex1233 Общие вопросы Javascript 3 22.08.2014 06:54
Как вы относитесь к наркоманам? Maxmaxmaximus7 Оффтопик 7 05.02.2014 13:29
Вопрос по jquery. Как запретить один из скриптов при клике vuler Общие вопросы Javascript 1 07.03.2012 22:35