x

Artículos técnicos sobre front-end y Ruby on Rails. Conocé también todas nuestras capacitaciones y búsquedas laborales.

Unite a más de 500 suscriptores que reciben nuestras novedades.

Our Blog

Volver

El misterioso mundo de Turbolinks y toda su magia


¿Turbolinks?

Para los que no conocen qué hace Turbolinks en detalle, podríamos describirlo como un snippet de javascript que permite cargar las páginas de una aplicación via AJAX. Cuando lo activamos en nuestro DOM, cualquier link que clickeamos es resuelto con una petición AJAX, donde el contenido de la petición se reemplaza en el DOM sin recargar la página entera, creando así una sensación de “rapidez” en los tiempos de respuesta de la aplicación.

Otra cosa copada que tiene Turbolinks es que usa el X-XHR-Referer como referrer, lo que permite hacer cosas copadas como, por ejemplo, no perder la habilidad de volver atrás (back button) después que seguimos un link que es resuelto con AJAX.

El lado oscuro de Turbolinks

Algo que es común escuchar (creería que yo lo repetí varias veces) es que, a la larga, es mejor sacar Turbolinks del proyecto para no tener que lidiar con los diferentes problemas de binding que podemos tener luego de que el contenido es reemplazado via AJAX.

Esta fue la razón que me llevó a ni siquiera considerar Turbolinks en Infohu, proyecto donde necesitaba refrescar todo el contenido, sin recargar la página.

Primero, intenté usando Wiselinks (muchos “entendidos” la consideran una mejor implementación que Turbolinks). Alternativa que descarté rápidamente, luego de chocar con el problema de perder los bindings que necesitaba preservar (sobre todo aquellos en los que no podía hacer una delegación del evento ‘click’ en document, para no perder la habilidad de hacer un stopPropagation).

Luego del fracaso con Wiselinks, mi segundo approach fue armar un snippet que ejecute mis links via AJAX. Si bien, este approach me dio más control y pude lograr más avance; hubo bindings que no pude lograr recargar. Sumado a esto, surgieron otros desafíos:

1) Si bien estaba haciendo un pushState para refrescar la URL, el back button dejó de funcionar. Tema indispensable a resolver.

2) Abortar peticiones AJAX existentes cuando se envía una nueva.

3) Recargar un binding a una función que necesita hacer un stopPropagation. Este caso se aplica para cuando quiero controlar un link a una acción vía delete. Controlar ese link (para mostrar un modal de confirmación antes) implica ejecutar un stopPropagation para evitar que el link sea resuelto por Rails (jquery-ujs).

4) Administrar un cache de los recursos que son pedidos, a fin de evitar pedirlos nuevamente.

Todo esto me llevó a descartar mi idea de “reinventar la rueda”.

Aprender a usarlo, para usarlo bien

Justo cuando empezaba a considerar la alternativa de implementar un JS framework (algo que, para el proyecto en cuestión, era un despropósito total), leí un artículo sobre Rails 5 donde hacían mención a Turbolinks, destacando todas las bondades que tendrá su versión 3 y recomendando su uso. Eso me hizo pensar en por qué algo con tantos problemas, seguía siendo incluido en Rails. Era evidente que había algo que no estaba haciendo bien; o que me faltaba profundizar sobre el tema.

Opté por setear Turbolinks en el proyecto, y rápidamente tenía este comportamiento mágico de que las páginas se recargaban sin refrescar la página. Lógicamente, surgió (nuevamente) el problema de los bindings, para lo que empecé a profundizar sobre cómo utilizar este recurso.

Efectivamente, el problema de los bindings existe en Turbolinks; pero es un problema que tiene solución: un orden específico para la carga de los scripts y una librería extra.

Por defecto, Rails genera la aplicación con un application.js que tiene este orden:

//= require jquery

//= require jquery_ujs

//= require turbolinks

Lo que uno hace, naturalmente, es colocar cualquier script al final de este manifesto y eso es un problema. Se recomienda que Turbolinks sea agregado al final del manifesto, luego de haber incluido todos los demás scripts. Luego, para lograr que nuestros bindings no se pierdan luego de una petición, es necesario poner un pequeño patch que “arregla” este defecto de Turbolinks.

Para incluir este patch, es necesario mantener un orden en la carga de los scripts, que es el siguiente:

//= require jquery

//= require jquery.turbolinks

//= require jquery_ujs

... el resto de nuestros scripts …

//= require turbolinks

Además, es necesario tener en cuenta algunos detalles:

1) Evitar hacer delegaciones dentro de un ‘on(ready)’. De esta manera, las delegaciones funcionan.

2) Se recomienda no utilizar “$(document).on('ready')”; en su lugar, hay que utilizar la forma más clásica (o menos “pro”) de “$(document).ready()”.

Aplicando todas estas consideraciones puedo garantizar que Turbolinks funciona sin entrometerse con ningún plugin o binding que tengamos en nuestra aplicación.

Bonus track

Así y todo, habrá veces que la página es refrescada. Nuevamente, leer la documentación puede ser muy útil para resolver este misterio.

Turbolinks se mantiene activo para cualquier redirección (``redirect_to``); sin embargo, es desactivado para peticiones que son resueltas con el render de una acción (ej: render :new), lo que provocará que la página sea refrescada.

Para solucionar esto, se puede hacer el render de un template (ej: render template: ‘projects/new’), y listo.

Para profundizar y no quedar estancado:

https://github.com/rails/turbolinks https://github.com/kossnocorp/jquery.turbolinks https://coderwall.com/p/ypzfdw/faster-page-loads-with-turbolinks

fuente de la imagen: Treehouse

3 Comments

  1. Genial.

    Soy nuevo en rails, estoy en la etapa de estudio. Luego de implementar varias acciones ajax mis formularios solo respondían cuando hacía un refresh. Colocando turbolinks al final las acciones comenzaron a funcionar sin refrescar. Muyyyyy pero muyyyyyyyyyy agradecido!.

    Hugo - 20 of February, 2017 at 04:20
  2. Releasing alongside the Black/Gum colorway for the men is this “String” iteration of the Nike Special Field Air Force 1.Just like every other pair, Nike Flyknit Racer this Nike Special Field Air Force 1 takes the tonal route as the entire upper comes done in a cream/off-white hue that Nike is Nike Janoski calling String. The shoe utilizes suede throughout the majority of the upper with ripstop ballistic nylon on the ankle area. Finishing things off is Nike Air Max rubber gum outsole for a clean aesthetic.The Nike Special Field Air Force 1 String will be releasing on January 19th 2017 for $165.
    The Nike Outlet Store Nike LunarCharge is a new silhouette that’s inspired from iconic styles – the Air Presto, Air Max 90, Air Flow and Air Current.Featuring a Nike Flyknit Lunar 3 low-cut construction that’s built with a combination of textiles and neoprene that includes an inner sleeve design borrowed from the Nike Ai

    Nike - 01 of March, 2017 at 03:20

Leave your comment

You are answering to

You have chars left