Артём Мáлков

Ещё один вариант отложенной загрузки скриптов на jQuery/JavaScript

1 авг22 комм

Если вы читаете эту статью, смею предположить, что вы, как и я в своё время, пытаетесь оптимизировать (ускорить загрузку страниц) сайт по рекомендациям Google PageSpeed Insights.

Что касается части, связанной с JavaScript, то формулировка рекомендаций в сервисе проверки скорости сайта (PageSpeed Insights) может быть следующей:

Устраните ресурсы, блокирующие отображение
Удалите неиспользуемый код JavaScript
Уменьшите влияние стороннего кода
Минимизируйте работу в основном потоке
Сократите время выполнения кода JavaScript
Предотвратите чрезмерную нагрузку на сеть

Внутренние скрипты (те, что находятся на вашем сайте) можно оптимизировать путём изменения логики их работы, когда как внешние лишены такой возможности и для них есть три варианта развития событий: загрузить их к себе на сайт и далее проводить необходимые работы (подходит не для всех случаев, так как вы можете потерять необходимую актуальность файлов), оставить всё как есть или отложить загрузку таких скриптов до нужного вам времени.

С первыми двумя случаями всё понятно, третий – собственно то, ради чего мы здесь и собрались.

Что на своей практике и на разных сайтах я пробовал:

  1. Загрузку скриптов после полной загрузки страницы (формально ускоряет работу сайта, но сервис проверки всё также ругается на проблемы).
  2. Отложенную загрузку скриптов через некоторое время (тоже вариант, но функционал сайта привязывается ко времени, и посетителю придется ждать, чтобы его увидеть).
  3. Комбинированный вариант первого и второго (для того, чтобы время во втором варианте отсчитывалось только после полной загрузки).
  4. Атрибут defer (чтобы не тормозить отрисовку страницы).
  5. Загрузку скриптов после какого-то взаимодействия с сайтом.

По первым 4 вариантам, думаю, всё понятно, и, скорее всего, вы их пробовали сами (если нет – попробуйте, чтобы понять, в чём вся суть), а вот последний мне показался перспективным, и именно его я решил «доводить до ума».

Забегая вперёд, показываю, что у меня получилось на jQuery:

var event_status = false; // Статус события (ещё не произошло)

$(window).on("load", function() {

	// Страница загрузилась полностью
			
	$(window).one("mouseover click scroll", function() {
		
		// Произошло нужное событие (mouseover, click или scroll) с объектом window
			
		if(!event_status) {
		
			// Если в первый раз
              
			alert("Привет!");
              
			event_status = true; // Статус события (произошло)

		}

	});

});

и аналог на JavaScript, для общего развития:

var event_status = false; // Статус события (ещё не произошло)

window.addEventListener("load", function() {

	// Страница загрузилась полностью
  
	["mouseover", "click", "scroll"].forEach(function(event) {
  
		window.addEventListener(event, function() {
		
			// Произошло нужное событие (mouseover, click или scroll) с объектом window
			
			if(!event_status) {
		
				// Если в первый раз
		
				alert("Привет!");
              
				event_status = true; // Статус события (произошло)

			}
		
		}, {
			once: true
		});
  
	});

});

Что и как здесь устроено?

Мы ждём, когда страница загрузилась полностью (это раз). Далее проверяем, выполнил ли человек одно (любое) из указанных действий на всей странице (движение курсора, клик, прокрутка) (это два). И три: после того, как выполнил, запускаем (или подгружаем) необходимый нам код.

Думаю, здесь всё понятно. Таким образом, мы сокращаем время загрузки страницы, и иногда ощутимо.

Перечень необходимых условий (действий) вы задаёте сами, можете привязать их даже к конкретным элементам.

В каких случаях я использую данную конструкцию? Когда идёт работа с внешними скриптами (различными чатами/консультантами, счётчиками, виджетами социальных сетей, картами и пр.). То есть когда нет возможности повлиять на содержимое файла, но можно регулировать момент его вовлечения в работу сайта. При этом никто не запрещает использовать такой подход и для локальных скриптов.

Рекомендуем к просмотру
Как добавить несколько обработчиков событий addEventListener() к одному элементу в JavaScript?
Статьи и советы
Аналог (эквивалент) метода one() из jQuery для JavaScript
Статьи и советы
Включаем сжатие текста и кэширование статических файлов на хостинге Ru-Center
Статьи и советы
22
комментария
Форма комментирования этого поста скрыта. Авторизуйтесь, чтобы расширить привилегии гостевого посещения и получить необходимую помощь от сообщества Pandoge.
    • 1
    30
      •  Проверенный
    19 ноя в 23:33

    Здравствуйте!

    Как отложить загрузку метрики и при этом отображался Ip пользователей?

    подскажите пожалуйста...

    <!--<script type="text/javascript" >  
    var yaParams = {ip:"<?php echo $_SERVER['REMOTE_ADDR'];?>"};
    (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
       m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
       (window, document, "script", "https://cdn.jsdelivr.net/npm/yandex-metrica-watch/tag.js", "ym");
    
       ym(86604927, "init", {
       params:window.yaParams,
            clickmap:true,
            trackLinks:true,
            accurateTrackBounce:true,
            webvisor:true
       });
    
    </script>-->
      • 1
      1066
        •  Команда Pandoge
      20 ноя в 10:32

      Sergey, здравствуйте!

      1. Вижу, что у вас закомментирован код счётчика, так как находится в

      <!-- -->

      2. На какой CMS и в каком месте вставляете этот код? Это нужно мне, чтобы подсказать вам с передачей IP-адреса. Вообще, насчёт IP рекомендую почитать этот пост - https://www.pandoge.com/post/753

      3. По идее, чтобы отложить загрузку Метрики нужно весь скрипт поместить в место, где размещён

      alert("Привет!");
      в примере. В вашем случае это будет выглядеть следующим:

      var event_status = false; // Статус события (ещё не произошло)
      
      $(window).on("load", function() {
      
      	// Страница загрузилась полностью
      			
      	$(window).one("mouseover click scroll", function() {
      		
      		// Произошло нужное событие (mouseover, click или scroll) с объектом window
      			
      		if(!event_status) {
      		
      			// Если в первый раз
                    
      			var yaParams = {ip:"<?php echo $_SERVER['REMOTE_ADDR'];?>"};
      (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
         m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
         (window, document, "script", "https://cdn.jsdelivr.net/npm/yandex-metrica-watch/tag.js", "ym");
      
         ym(86604927, "init", {
         params:window.yaParams,
              clickmap:true,
              trackLinks:true,
              accurateTrackBounce:true,
              webvisor:true
         });
                    
      			event_status = true; // Статус события (произошло)
      
      		}
      
      	});
      
      });

      Сразу хочу сказать, что откладывание счётчика может сказаться на корректности сбора статистики. Тут рекомендую потестировать

      • 1
      30
        •  Проверенный
      20 ноя в 21:49

      Артём Мáлков, сайт самопись, поставил ваш код, но ip не отображается,

      у вас есть свой вариант? ну типо как на этом https://www.pandoge.com/post/753

      но с отложенной загрузкой

      • 1
      30
        •  Проверенный
      22 ноя в 20:34

      Артём Мáлков, ?

      • 1
      1066
        •  Команда Pandoge
      изменено 22 ноя в 23:29

      Sergey, то, что я выше сделал пример - не работает? В каком месте/файле подключаете? Можете прислать ссылку на сайт?

      • 1
      30
        •  Проверенный
      23 ноя в 11:27

      Артём Мáлков, файл index.php

      в секцию <head> . 24goodwashing.ru/index(1) .php

      • 1
      1066
        •  Команда Pandoge
      30 ноя в 00:24

      Sergey, решили вопрос? Просто вижу, что IP в коде отображается и отложили выполнение другим способом

      • 1
      30
        •  Проверенный
      30 ноя в 11:58

      Артём Мáлков, еще нет

      • 1
      1066
        •  Команда Pandoge
      30 ноя в 12:39

      Sergey, тогда давайте сделаем это. Что сейчас не получается?

      • 1
      30
        •  Проверенный
      30 ноя в 20:35

      Артём Мáлков, вроде метрика работает при таком отложенном варианте но не работает IP.

      То есть не собирает Ip пользователей, а при простом коде метрики без lazyload то работает

      • 1
      1066
        •  Команда Pandoge
      30 ноя в 20:51

      Sergey, то есть если метрика отложена, то не передается IP, а если не отложена - передаётся? В каком месте вы смотрите IP в метрике?

      • 2
      30
        •  Проверенный
      30 ноя в 21:55

      Артём Мáлков, все верно

      В параметры визита

      • 1
      1066
        •  Команда Pandoge
      изменено 1 дек в 01:14

      Sergey, давайте попробуем изменить принцип передачи IP. Попробуйте так (пока без отложенной загрузки):

      <script type="text/javascript" >  
      (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
         m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
         (window, document, "script", "https://cdn.jsdelivr.net/npm/yandex-metrica-watch/tag.js", "ym");
      
         ym(86604927, "init", {
              clickmap:true,
              trackLinks:true,
              accurateTrackBounce:true,
              webvisor:true
         });
      
         ym(86604927, "params", {ip: "<?php echo $_SERVER['REMOTE_ADDR'];?>"});
      
      </script>
      • 1
      30
        •  Проверенный
      2 дек в 22:53

      Артём Мáлков, да IP показывает

      • 2
      1066
        •  Команда Pandoge
      3 дек в 22:27

      Sergey, теперь давайте попробуем добавить отложенную загрузку:

      <script>
      
      	var event_status = false; // Статус события (ещё не произошло)
      
      	$(window).on("load", function() {
      
      		// Страница загрузилась полностью
      				
      		$(window).one("mouseover click scroll", function() {
      			
      			// Произошло нужное событие (mouseover, click или scroll) с объектом window
      				
      			if(!event_status) {
      			
      				// Если в первый раз
      				  
      				(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
      			   m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
      			   (window, document, "script", "https://cdn.jsdelivr.net/npm/yandex-metrica-watch/tag.js", "ym");
      
      			   ym(86604927, "init", {
      					clickmap:true,
      					trackLinks:true,
      					accurateTrackBounce:true,
      					webvisor:true
      			   });
      
      			   ym(86604927, "params", {ip: "<?php echo $_SERVER['REMOTE_ADDR'];?>"});
      
      				event_status = true; // Статус события (произошло)
      
      			}
      
      		});
      
      	});
      
      </script>
      • 2
      30
        •  Проверенный
      4 дек в 16:13

      Артём Мáлков, ваш вариант работает)!

      • 2
      30
        •  Проверенный
      4 дек в 16:13

      Артём Мáлков, спасибо)!

      • 1
      1066
        •  Команда Pandoge
      5 дек в 09:26

      Sergey, хорошо, что удалось решить задачу angel

    • 1
    30
      •  Проверенный
    29 дек в 09:04

    Добрый день!

    А можно ли отложить загрузку recaptcha?

    Сайт на Joomla, плагин CAPTCHA - reCAPTCHA

    • 1
    30
      •  Проверенный
    13 окт в 20:13

    Добрый день!

    Сможете ли вы сделать статью о Ускорении сайта Bitrix, ну мало про это информация.

    Буду благодарен)

      • 1
      1066
        •  Команда Pandoge
      14 окт в 17:49

      Sergey, здравствуйте!

      Где бы найти время eek, а так есть опыт в этом вопросе. Если получится - напишем.

      • 4
      30
        •  Проверенный
      14 окт в 17:53

      Артём Мáлков, спасибо!

Подняться наверх
«Pandoge» - помощник вебмастера