Событие загрузки Turbolinks не работает при загрузке страницы

У меня проблема с текущим событием рекомендованной загрузки турболыков по умолчанию:

document.addEventListener('turbolinks:load', function() {
  …
});

Случается, что это не срабатывает в Safari при загрузке страницы. Поэтому я добавил Turbolinks.dispatch("turbolinks:load"); к application.js.

Казалось, все работает нормально. Но в Chrome он сработал автоматически, поэтому в итоге произошло двойное срабатывание turbolinks:load события.

Моим первым решением было запускать turbolinks:load только в браузерах, отличных от Chrome.

Но почему-то даже в Chrome некоторые представления не запускаются turbolinks:load автоматически. Так что мне пришлось запускать его и на определенных представлениях.

Последнее решение, которое я нашел, заключалось в следующем:

$(document).on('ready turbolinks:load', function() {
  …
});

Кажется, это решает все проблемы, потому что он срабатывает при загрузке или перезагрузке первой страницы, а также при нажатии на ссылки. Он также запускается в Chrome и Safari.

Есть ли лучший способ справиться с этим?

Документы говорят, что первая версия верна, но, похоже, это не так.

Я что-то упустил?

(примечание: использование jQuery не является для меня недостатком, и я знаю, что смогу реализовать это с помощью пары document.addEventListener)


person lucasarruda    schedule 01.05.2018    source источник
comment
Как у вас загружается в Turbolinks? т.е. где ваши теги сценария на странице и используете ли вы async на <script>?   -  person Dom Christie    schedule 02.05.2018
comment
Я загружаю обычный Rails в конвейер ресурсов. Затем я переместил его с тела на голову и добавил к нему асинхронность. Загрузка всего в один js (application.js), поэтому у меня нет проблем с асинхронностью.   -  person lucasarruda    schedule 02.05.2018


Ответы (1)


Как отмечено в комментариях, вы загружаете Turbolinks с async. Turbolinks в настоящее время не работает при асинхронной загрузке. Поэтому лучший совет на данный момент - удалить атрибут async из тега скрипта или использовать вместо него defer.

Почему?

Turbolinks прослушивает событие DOMContentLoaded при первой загрузке, чтобы затем запустить turbolinks:load. При его асинхронной загрузке возможно, что сценарий завершит загрузку / выполнение после анализа HTML и DOMContentLoaded запуска. В этом случае turbolinks:load не будет запущен.

В настоящее время существует проблема GitHub для обсуждения некоторых возможных решений для реализации библиотеки: https://github.com/turbolinks/turbolinks/issues/281

person Dom Christie    schedule 03.05.2018
comment
Понятно, спасибо за ответ. Таким образом, даже загрузка турболыков внутри этого application.js (все они там собраны) проблематична при использовании async. Должен ли я тогда использовать defer? В противном случае мне пришлось бы переместить его из заголовка, что нарушает суть. - person lucasarruda; 03.05.2018
comment
да. Turbolinks зависит от события DOMContentLoaded, которое может сработать до загрузки и выполнения application.js. Использование defer должно быть нормальным, поскольку DOMContentLoaded запускается после загрузки и выполнения скриптов. Стоит отметить, что даже без defer скрипт application.js будет блокироваться только при первой загрузке. Последующие загрузки Turbolink не будут затронуты. FWIW, я не думаю, что разработчики Turbolinks используют defer. Не помещайте свой application.js в ‹body›. - person Dom Christie; 04.05.2018
comment
Спасибо за ответ. Меня беспокоит, что размещение в голове без defer приведет к увеличению первой загрузки, уменьшению рейтинга Google / SEO, а вы знаете историю. Тогда я сделаю тест с defer. - person lucasarruda; 04.05.2018
comment
Лично я бы не стал слишком особо беспокоиться о размещении вашего скрипта в ‹head›, если размер файла не будет огромным. - person Dom Christie; 09.05.2018
comment
Он небольшой, менее 300 КБ, но я думаю, что это сильная рекомендация от Google с точки зрения SEO / оптимизации страницы. - person lucasarruda; 09.05.2018
comment
OK. Возможно, стоит провести аудит производительности / SEO в Chrome, чтобы увидеть, насколько большое влияние это оказывает. FWIW для основного приложения, над которым я работаю, мы не откладываем загрузку скриптов и получаем оценку SEO 89 и оценку производительности 82, поэтому это может не иметь большого значения для того, как Google оценивает вашу страницу. Однако файл application.js составляет всего 81,3 КБ (минимизированный / сжатый с помощью gzip). - person Dom Christie; 11.05.2018
comment
Сделаю это. Мне любопытно, не видите ли вы эту рекомендацию в инструменте Google Page Speed. - person lucasarruda; 11.05.2018
comment
Да, это рекомендация, но, учитывая достаточно высокие показатели производительности / SEO, это говорит о том, что это может не иметь большого значения (в моем случае). - person Dom Christie; 11.05.2018
comment
Ну ладно, понял. Сейчас мы живем в 90-е, так что я думаю, это помогло. - person lucasarruda; 11.05.2018
comment
Я не тестировал одну версию по сравнению с другой, но у меня периодически возникали проблемы, когда иногда код внутри $(document).on('ready turbolinks:load', function() { вызывал дважды. А теперь перемещение async в defer заставляет document.addEventListener('turbolinks:load', function() { работать правильно, и он срабатывает только один раз во всех протестированных случаях. Так что определенно правильный подход (с defer или без чего-либо). Спасибо за помощь! - person lucasarruda; 15.05.2018