- PVSM.RU - https://www.pvsm.ru -

Тонкости Rails 4 — Turbolinks

Тонкости Rails 4 — Turbolinks

Гем под названием Turbolinks [1] способен неплохо ускорить ваше приложение, используя JavaScript для обновления контента на странице. Он включен по умолчанию в Rails 4, но я покажу, как можно использовать его уже сейчас в программах, написанных на Rails 3. Также вы узнаете о некоторых подводных камнях.


Cодержание цикла «Тонкости Rails 4»


Turbolinks позволяет ускорить практически любое Rails-приложение, поскольку загружает только тело страницы страницы, а не всю ее целиком. Да, делается это все добро с помощью JavaScript. В этой статье мы опробуем работу гема на приложении, написанном на третьих рельсах.

Сам сайт достаточно прост — это набор проектов со своим списком задач, которые необходимо выполнить. Каждая новая задача помечается как неоконченная, но легким движением мышки (а вернее, нажатия в соответствующем чекбоксе) задача превращается в завершенную.

Тонкости Rails 4 — Turbolinks

Добавление Turbolinks

Теперь добавим Turbolinks в наше приложение и посмотрим, как все это работает. В первую очередь необходимо вписать имя гема в gemfile и затем запустить bundle install.

/Gemfile

gem 'turbolinks'

Теперь необходимо добавить в Javascript манифест приложения строчку для добавления turbolinks:

/app/assets/javascripts/application.js

//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .

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

Перегрузив после этого сервер рельс и полазив немного по приложению возможно вы не увидите особой разницы. Чтобы проверить, а работает ли собственно Turbolinks необходимо открыть network inspector браузера и затем уже побродить по сайту. В моем случае, после описанных выше шагов я увидел, что при переходе на какую-либо страницу она загружается целиком, таким образом вывод: гем не заработал. Это может происходить в том случае, если ваш браузер не поддерживается Turbolink’ом, в таком случае стоит его сменить (и, желательно, на что-то известное), либо обновиться (если это возможно). Гем ожидает, что используется наиболее свежая версия одного из популярных браузеров. Иначе он просто не будет работать, но при этом приложение будет функционировать нормально и без него.



В моем случае я поменял мой браузер на новую версию Chrome и открыл в нем разрабатываемый сайт. Запустив веб-инспектор и покликав по ссылкам будет видно, что страница не перегружается полностью, поскольку теперь гем работает и turbolinks.js уже генерирует ajax-запрос для открываемой страницы.

Тонкости Rails 4 — Turbolinks

Использование гема позволяет сайту загружаться быстрее, поскольку браузер не занимается заново интерпретацией JS и CSS кода, но как же все же это работает?

Turbolinks для всех ссылок на странице слушает событие click. Как только оно происходит, к нужной странице делается GET-запрос через JavaScript и после этого анализируются полученные данные, а затем обновляются элементы title и body. Гем также использует Push State API для изменения URL обновленной страницы. Подобная техника очень похожа на PJAX.

Тонкости Rails 4 — Turbolinks

Проблемы с уже существующими скриптами

Написанное для этого урока приложение, казалось бы, работает с Turbolinks довольно неплохо, но тем не менее, даже в нем возникают проблемы с существующими скриптами на JavaScript. Увидеть эту проблему очень просто, стоит всего лишь попытаться переключить значение в чекбоксе задачи. Ничего не произойдет. Вообще. Однако, если вручную обновить страницу, то проблема волшебным образом испарится.


Собственно, вот код, с которым возникают проблемы:

/app/assets/javascripts/projects.js.coffee

jQuery ->
  $('.edit_task input[type=checkbox]').click ->
    $(this).parent('form').submit()

Код ожидает событие click в одном из чекбоксов задач. Как только оно произошло, форма с чекбоксом отправляется на сервер, после чего задача помечается как завершенная.

Приглядитесь к первой строке кода. Она очень важна, поскольку именно в ней происходит ожидание события ready для страницы, срабатывающий только после того, как DOM страницы целиком загрузился. Поэтому, если не использовать этот код, то jQuery попытается приаттачить event'ы к чекбоксам еще до их загрузки.

При использовании Turbolinks этот callback исполняется только один раз, при загрузке страницы. Это подводит нас к другой важной мысли: при переходе на другую страницу, благодаря вышеописанным особенностям гема чисто технически мы остаемся на той же самой странице. Однако сам Turbolinks генерирует несколько различных событий при загрузке новой странице и один из них — page:load. Это позволяет эмулировать загрузку DOM:

/app/assets/javascripts/projects.js.coffee

ready = ->
  $('.edit_task input[type=checkbox]').click ->
    $(this).parent('form').submit()

$(document).ready(ready)
$(document).on('page:load', ready)

Теперь можно определить переменную ready, сохранить в ней нашу многострадальную функцию, после чего передать переменную в document.ready и page:load. Таким образом, события теперь прикреплены к чекбоксам в независимости от того, используется Turbolinks или нет. Теперь функциональность восстановлена: при проставлении галочки в чекбоксе задачи она будет автоматически помечена как завершенная. И также легко оконченную задачу можно превратить в незавершенную.

Для решения похожих проблем можно воспользоваться Jquery Turbolinks gem [3]. Кроме того, существует еще одно решение для обхода подобных подводных камней. Вместо того, чтобы находить элементы и отслеживать их click события можно слушать событие click для всего документа и при его возникновении проверять, что оно было вызвано для чекбокса с задачей:

/app/assets/javascripts/projects.js.coffee

$('document').on 'click', '.edit_task input[type=checkbox]', ->
    $(this).parent('form').submit()

При таком подходе даже нет необходимости проверять, что DOM загружен. И также есть дополнительное преимущество: код будет корректно обрабатывать все задачи с чекбоксами, добавленные с помощью AJAX.

Хорошей идеей будет следить за баг-трекером Turbolinks [4], поскольку на момент публикации статьи у него были серьезные проблемы со сторонними библиотеками, такими как Twitter Bootstrap, Jquery UI Calendar. При этом над ними идет с работа с целью добавления совместимости.

Тем не менее существуют нечастые ситуации, в которых при возврате на предыдущую страницу Turbolinks мило делает POST-запрос, вместо GET. Как решить эту проблему? Просто отключите Turbolinks в подобных ситуациях. Эти детские болезни должны быть вылечены в скором будущем.

Посмотрев на такую кучу проблем можно подумать: «А стоит ли оно того?». Помочью решении может тест скорости Turbolinks [5], из которого видно, что в некоторых случаях загрузка страницы повышается в 2 раза. Конечно, все приложения разнятся, но вы можете попробовать гем у себя и проверить, насколько улучшится отзвычивость сайта.

Если же хочется использовать Rails 4 и при этом Turbolinks вам категорически не нравится или не подходит, то его спокойно можно отключить. Для этого необходимо убрать гем из gemfile, а затем удалить соответствующую строку с require из главного JavaScript манифеста приложения.

Спасибо за внимание!

Обо всех найденных ошибках, неточностях перевода и прочих подобных вещах просьба сообщать в личку.


Приложение


Воспользуетесь ли вы Turbolinks в ваших проектах?

Только зарегистрированные пользователи могут участвовать в опросе. Войдите [7], пожалуйста.

Проголосовало 3 человека. Воздержалось 3 человека.

Автор: Loremaster

Источник [8]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/ruby/25813

Ссылки в тексте:

[1] Turbolinks: https://github.com/rails/turbolinks

[2] Cache digests: http://habrahabr.ru/post/165355/

[3] Jquery Turbolinks gem: https://github.com/kossnocorp/jquery.turbolinks

[4] баг-трекером Turbolinks: https://github.com/rails/turbolinks/issues

[5] тест скорости Turbolinks: https://github.com/steveklabnik/turbolinks_test

[6] Исходный код приложения из урока: http://media.railscasts.com/assets/episodes/sources/390-turbolinks.zip

[7] Войдите: https://www.pvsm.ru/login/

[8] Источник: http://habrahabr.ru/post/167161/