Перенос загрузки скриптов JS в футер

+19
3.34K
День добрый,

Почему нужно грузить js после контента можно почитать, например тут. Если кратко — это нужно для того, чтобы ускорить загрузку страниц. В блогах и на форуме готового решения не нашел, если пропустил — кидайте в комментах.

На гите инициатива делить теги на те, что нужно грузить в head и те, что в перед </body> потерпела неудачу (возможно, моей аргументации не хватило), поэтому напишу что можно сделать на текущий момент для реализации этой идеи.

На InstantCMS2 есть для этого механизм — почти без танцев, почти без бубна. Но некоторые нюансы есть, поэтому появилось желание оформить это постом.

В чем сложность:
Нам надо оставить часть скриптов сверху, а часть снизу — а функция для вывода js только одна $this->printJavascriptTags. Сверху должна быть статистика и те скрипты, без которых код на странице выдаст ошибки при загрузке.

Решение этой задачи сводится к внесению изменений в один файл шаблона main.tpl.php. Минус в том, что мы больше не сможем использовать методы addMainJS, addControllerJS, addJSFromContext для скриптов, которые нужно загрузить в секцию head, но если на кону скорость загрузки страницы… Еще минус в том, что мы грузим jquery напрямую и возможны ситуации, когда этот скрипт повторно загрузится снизу… Обычно такого не должно быть, но ситуация возможна.

Решение

1. Подключаем jquery в блоке head напрямую.
В шаблоне вместо
  1. <?php $this->addMainJS("templates/{$this->name}/js/jquery.js"); ?>
вставляем строку
  1. <script type="text/javascript" src="/templates/default/js/jquery.js"></script>
2. Грузим сверху все css и другие теги (сюда могут попасть и js, которые добавлены через функцию addHead)
Заменяем строку
  1. <?php $this->head(); ?>
на
  1. <?php $this->head(true, false, true); ?>
3. Добавляем перед </body> строку
  1. <?php $this->printJavascriptTags(); ?>
После этих замен сверху будут грузиться все стили, jquery и другие теги, которые добавлены через метод addHead.

Остается вопрос — что делать со скриптами, которые обязательно должны грузиться сверху? — их нужно подключать не через addMainJS или addControllerJS. Подключать их теперь нужно только через addHead и тогда они попадут в блок <head></head>.
Олег Васильевич я Олег Васильевич я 6 лет назад #
Комментарий удален
Олег Васильевич я Олег Васильевич я 6 лет назад #
Комментарий удален
0
SmartControl SmartControl 6 лет назад #
Прочитал в документации про наследование - не пострадает. Все изменения вносятся в main.tpl.php основного шаблона, а наследование то касается подключаемых файлов - шаблонов страниц и CSS/JS файлы.
+2
My-InstantCMS.Ru My-InstantCMS.Ru 6 лет назад #
Когда то тоже занялся этим вопросом, в итоге решил что подключаемые js скрипты должны оставаться на верху.
Уже не помню какие проблемы возникли, но core.js, rating.js и еще несколько, должны быть на верху, так как перед footer-ом есть такой код https://prnt.sc/ginla2

По этому, без таких методов как $this->addFooterJS() и для вывода $this->footer() на мой взгляд не получиться грамотно реализовать
0
SmartControl SmartControl 6 лет назад #
Согласен, нужны обновления соответствующие. На гите у меня с первого раза не вышло это доходчиво донести и предложение было отклонено - вот может этот пост даст более качественную аргументацию почему это нужно сделать на уровне движка.
0
spartak spartak 6 лет назад #
Заодно может рассмотрят код core.js..ну или хотя бы сделают отдельные core.js для шаблона сайта и шаблона админки..В админке половина кода из этого файла вообще не нужно.. в шаблоне сайта приходиться редактировать этот файл постоянно..на пример при подключении bootstap очень мешает использование тегов nav в этом файле...Извиняюсь. Отошел от темы.
0
vikont vikont 6 лет назад #
Хочу вас огорчить, уже поднимался этот вопрос, на что "отцы создатели" Инстанта предложили не заморачиваться и отправить Гугломерку скорости загрузки страниц куда подальше....
Предполагаю, что данный вопрос пока труднореализуемый или действительно не стоит всех усилий.
0
SmartControl SmartControl 6 лет назад #
Да причём тут гугломерка.. тут вопрос как быстро пользователь страницу увидит. Реализовать просто, но если желания делать это красиво нет, то каждый будет под себя настраивать.
0
letsgo letsgo 6 лет назад #
Себе делал, но также пришёл к выводу что лучше сверху. Скорость показатели можно и другим догнать, но подмигивание при загрузке некрасиво.
0
SmartControl SmartControl 6 лет назад #
Да, возможно. Вообще - это неправильное решение. Делать надо по-другому.. Но это придется хакать файлы движка, чего не хочется (по-крайней мере в паблик я это писать не буду - сделаю для себя только).
Нельзя массово переносить скрипты вниз. этим нужно управлять. Не все скрипты приводят к "подмигиванию", какие-то можно безболезненно убрать вниз.
+1
Fuze Fuze 6 лет назад #
Нет смысла убирать скрипты выборочно, если стремиться к показателям. Второе, просто так скрипты вниз перенести нельзя, есть еще инлайновые скрипты, использующие jquery и которые перестанут работать. Все

Код JAVASCRIPT:
  1. $(function(){
  2. // что-то там
  3. });
нужно менять на что то вроде

Код JAVASCRIPT:
  1. document.addEventListener('DOMContentLoaded', function (){
  2. // что-то там
  3. });
0
SmartControl SmartControl 6 лет назад #
Нет смысла убирать скрипты выборочно, если стремиться к показателям

Простой пример. У меня есть компонент, который грузит 200кб скриптов - я их подключаю у себя снизу (добавил хук "print_footer"), потому что незачем тратить время на загрузку пользователем 200кб скрипта. Но я не могу дать пользователям такую возможность без правок шаблона, а добавлять такое требование к компоненту не хочу - это усложняет использование компонента.. В итоге получается все пользователи вынуждены замедлять загрузку страницы из-за одного компонента, который этого даже не требует - ему все-равно где и что подгружать.

Решение для себя вижу в добавлении доп настроек - если пользователь руками хочет добавить хук, то скрипт будет подключаться внизу. Если не хочет, то сверху со всеми вместе.

Второе, просто так скрипты вниз перенести нельзя, есть еще инлайновые скрипты, использующие jquery и которые перестанут работать.
Согласен, в моем решении (которое в посте и описано) jquery принудительно грузится сверху. В все остальное внизу.
0
Val Val 6 лет назад #
Физически время полной загрузки страницы не меняется от положения скриптов на ней)) Меняется ощущение пользователя, т.е. уменьшается время пока пользователь увидит первый текст на странице.
Т.к. это CMS т.е. система для сайтостроителей без глубоких знаний программирования, то при переносе скриптов к футеру резко повышается вероятность всевозможных ошибок инлайн скриптов которые сделаны так чтобы сразу выполняться (и это не оф. разработчики так делают, а сторонние горе программисты или сами админы сайтов находят на просторах интернета). И посыпятся куча претензий от таких сайтостроителей что ничего не работает и во всем этом виноват движок, а не их кривые руки.
И последнее, если не ошибаюсь в современных стандартах и современных браузерах (IE 10+) подгружать скрипты можно в неблокирующем асинхронном режиме ( ссылка). По сути тот же эффект что и перемещение к закрывающему тегу body. Можно в функции типа addJS(), addMainJS() и др. добавить флаг is_async или is_defer кому надо чтобы пользовался)) без костылестроения.
0
SmartControl SmartControl 6 лет назад #
Физически время полной загрузки страницы не меняется от положения скриптов на ней))
Все верно. От перемены мест слагаемых сумма не меняется. Забота именно о картинке, которую увидит пользователь - ускорить ее появление.

Т.к. это CMS т.е. система для сайтостроителей без глубоких знаний программирования, то при переносе скриптов к футеру резко повышается вероятность всевозможных ошибок инлайн скриптов
И тут согласен, я ж изначально хотел сервис для разработчиков. Которые бы сами решали какие из их скриптов нужно перенести в конец. А не для вебмастеров, которые могут что-то сломать. Я делаю компонент и я хочу убрать свой скрипт вниз - вот так. И я сам уже думаю (как автор компонента) можно это сделать или нет.

И последнее, если не ошибаюсь в современных стандартах и современных браузерах (IE 10+) подгружать скрипты можно в неблокирующем асинхронном режиме
Да, это вариант. Если нам не важен порядок загрузки скриптов, потому что при такой загрузке скрипты загрузятся не по порядку следования в документе, а как попало - асинхронность она ж такая...

Я нашел решение, как буду делать для своих компонентов.. Это будет просьба для пользователей добавить хук в перед </body>, в противном случае загрузка в head c атрибутом async - это не самый плохой вариант.
0
Val Val 6 лет назад #
@SmartControl:
Если нам не важен порядок загрузки скриптов, потому что при такой загрузке скрипты загрузятся не по порядку следования в документе, а как попало
Не совсем, почитайте подробнее про defer ;)
С другой стороны, блокировки контента не будет, эффект пользователя достигнет, а то что какой либо скрипт подгрузится позже (не в порядке следования) на работоспособность страницы не повлияет (если конечно с умом подходить к вопросу).
Олег Васильевич я Олег Васильевич я 6 лет назад #
Комментарий удален
0
Val Val 6 лет назад #
Как я ниже описал двумя строками кода решить вопрос не получится. Поэтому прежде чем с головой окунаться в проблему, хотелось бы от разработчиков знать - а надо ли? В противном случае можно потратить время, сделать решение которое все равно не будет востребовано.
0
SmartControl SmartControl 6 лет назад #
Стоп, вы предлагаете добавить костыль в addJS(), addMainJS(), чтобы работать без костылестроения?)) - так в том то и вопрос, что нужно обновить движок, чтобы все было красиво. Я же с этого и начинал. Сейчас возможностей не хватает, чтобы делать со скриптами то, что хочется.

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

Я вас прекрасно понимаю, про is_async и is_defer, но сейчас это костыли.
0
Val Val 6 лет назад #
У нас разное видение костылестроительной отрасли smile
Я предложил вариант по примеру функций html компонентов (html_input, html_textarea и др.). В них есть возможность добавлять свои атрибуты для тега ( $attributes=array() ). Но просто так добавить атрибуты в JS (и CSS) нельзя. Конечно нужно допиливать весь механизм сбора js-тегов их мерж и вывод. В текущей версии движка из коробки этого нет. Если сделать получим возможность сбора всех JS в одном месте и не блокированную загрузку тех из них которые разработчик дополнения посчитал возможным и необходимым это сделать. Т.е. более логично все скрипты видеть в одном месте чем разбросанными по странице.

Откровенно говоря лишь единицы захотят разбираться с асинхронностью и допиливать свои дополнения чтобы страница прогрузилась на 70 мсек быстрее)). Поэтому "овчинка не стоит выделки".
Я лишь указал что такое возможно. Но я не говорил что это делается в 2 клика.

Если делать, то делать все в одном месте или внизу или вверху. Внизу для универсальной CMS опасно. Поэтому логично сделано вверху. Если хочется получить возможность оптимизации загрузки - то логичнее дорабатывать атрибуты, а не разбрасывать скрипты по странице.
0
SmartControl SmartControl 6 лет назад #
Откровенно говоря лишь единицы захотят разбираться с асинхронностью и допиливать свои дополнения чтобы страница прогрузилась на 70 мсек быстрее)). Поэтому "овчинка не стоит выделки".

Я бы добавил - лишь единицы могут разрабатывать компоненты, поэтому можно не париться)) Позиция не супер для универсальной CMS.. Нужно добавлять и атрибуты (атрибуты может быть важнее и приоритетнее - да и проще) и вывод внизу - я все-таки думаю, что должна быть универсальность.

Какой -то забавный спор выходит. Первая позиция - "надо сделать универсальней". Вторая - "да ладно, и так пойдет". Если пойдет, то конечно можно не продолжать) Как-нибудь и так будет работать, работало же раньше, можно и не пытаться сделать лучше и быстрее - не пойдем на поводу у гугломерок.

Для нормальных посещаемых сайтов и 70 мсек имеют значение если это задержка только от одного компонента. которых могут быть десятки.
0
SmartControl SmartControl 6 лет назад #
SmartControl:
Я вас прекрасно понимаю, про is_async и is_defer, но сейчас это костыли.

Точнее их можно использовать только в функции addHead - там все что хочешь.. И атрибуты, и теги и тд.. И все выведется сверху.

Еще от автора

Stylik - визуальный редактор CSS стилей
Всем привет, Это первый компонент из серии (Шаблон + Лендинг + Редактор). Он позволяет кастомизицировать любой шаблон под InstantCMS 2.
Smart Шаблон на Bootstrap 4, Первое знакомство
Приветствую. В этом шаблоне нет привычной заранее заданной схемы позиций. Любая схема создается вручную за пару минут.
Загрузка с Google Images и Релевантные видео Youtube
Приветствую, В этом посте расскажу сразу про две доработки.
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.