RefreshLess

Añade una capa de navegación basada en JavaScript sobre el HTML renderizado en el servidor de Drupal para proporcionar una experiencia de usuario fluida, rápida y similar a una SPA, manteniendo la mejora progresiva.

refreshless
7 sites
66
drupal.org

Overview

RefreshLess transforma las páginas tradicionales renderizadas en el servidor de Drupal en una experiencia fluida y responsiva similar a una aplicación de página única (SPA) sin sacrificar la mejora progresiva. Construido sobre la biblioteca Hotwire Turbo, intercepta la navegación de páginas y los envíos de formularios, cargando nuevo contenido mediante AJAX y actualizando el DOM de forma transparente mientras preserva el JavaScript y CSS ya cargados.

A diferencia de las SPAs completamente del lado del cliente, RefreshLess mantiene un respaldo completo a las cargas de página tradicionales si JavaScript falla, asegurando que tu sitio permanezca funcional en condiciones de red adversas. Este enfoque reutiliza las plantillas Twig existentes de Drupal, el sistema de bibliotecas de assets, el almacenamiento en caché y las características de seguridad, eliminando la necesidad de reimplementar un front-end separado.

Las capacidades principales incluyen gestión inteligente de hojas de estilo y scripts entre navegaciones, almacenamiento en caché de páginas del lado del cliente para navegación instantánea hacia atrás/adelante, transiciones de página opcionales con animaciones CSS o la API View Transitions, precarga diferida de enlaces, e integración perfecta con el sistema AJAX de Drupal, diálogos, enlaces contextuales y biblioteca de medios.

Features

  • Navegación basada en JavaScript que intercepta clics en enlaces y envíos de formularios, cargando contenido mediante la API fetch y actualizando el DOM sin recargas completas de página
  • Mejora progresiva con respaldo automático a cargas de página tradicionales cuando JavaScript falla o no está disponible
  • Gestión inteligente de assets que rastrea las bibliotecas CSS y JavaScript cargadas entre navegaciones, cargando solo nuevos assets cuando es necesario
  • Almacenamiento en caché de páginas del lado del cliente impulsado por Turbo para navegación instantánea hacia atrás/adelante y renderizado de vista previa mientras se obtiene contenido fresco
  • Transiciones de página opcionales con animaciones CSS personalizables y soporte para la API View Transitions
  • Precarga diferida de enlaces que utiliza IntersectionObserver para precargar enlaces en caché a medida que aparecen en la vista al desplazarse
  • Servicio de mensajería decorado que preserva los mensajes flash en escenarios de recarga de Turbo
  • Capas de compatibilidad para características del núcleo de Drupal incluyendo AJAX, diálogos, enlaces contextuales, biblioteca de medios, módulo de navegación y selección de tablas
  • Indicador de barra de progreso que muestra el estado de carga de la página durante la navegación
  • Servicio de interruptor de apagado para deshabilitar RefreshLess programáticamente para solicitudes específicas
  • Contextos de caché para renderizado condicional basado en el estado de RefreshLess

Use Cases

Sitios web con mucho contenido que requieren navegación rápida

RefreshLess es ideal para sitios Drupal ricos en contenido donde los usuarios navegan frecuentemente entre páginas. Al eliminar las recargas completas de página, la navegación se siente instantánea mientras mantiene los beneficios SEO del contenido renderizado en el servidor. El almacenamiento en caché del lado del cliente hace que la navegación hacia atrás/adelante sea instantánea.

Mejora progresiva para sitios de misión crítica

Para sitios web que deben funcionar de manera confiable independientemente de la disponibilidad de JavaScript (sitios gubernamentales, salud, proceso de pago de comercio electrónico), RefreshLess proporciona una experiencia de usuario tipo SPA mientras recurre automáticamente a la navegación tradicional si JavaScript falla. Esto asegura un 100% de tiempo de actividad para la funcionalidad central.

Sitios con inicialización de JavaScript costosa

Si tu sitio carga bibliotecas JavaScript sustanciales o tiene rutinas de inicialización complejas, RefreshLess elimina el costo de reinicializar en cada carga de página. CSS y JavaScript se cargan de forma aditiva solo cuando se necesitan nuevos assets.

Interfaces de administración con navegación frecuente

Las interfaces de administración de Drupal se benefician significativamente de RefreshLess ya que los editores navegan frecuentemente entre listados de contenido, edición y páginas de configuración. Combinado con el módulo de integración Gin, los flujos de trabajo de administración se vuelven notablemente más rápidos y responsivos.

Sitios que requieren transiciones de página y animaciones

Usando el submódulo refreshless_transitions, los sitios pueden implementar transiciones de página suaves con animaciones CSS o la moderna API View Transitions, creando experiencias similares a aplicaciones mientras mantienen la navegación tradicional basada en URLs.

Sitios web móviles primero

El submódulo refreshless_preloader es particularmente valioso para usuarios móviles donde la precarga basada en hover no funciona. Los enlaces se precargan a medida que los usuarios los desplazan hacia la vista, haciendo la navegación subsiguiente instantánea.

Tips

  • Todo el JavaScript de RefreshLess usa el atributo defer para una carga óptima. Asegúrate de que tu JavaScript personalizado también use defer para compatibilidad.
  • Usa el atributo data-refreshless-temporary en elementos que no deben ser almacenados en caché, similar al atributo data-turbo-temporary de Turbo.
  • Al escribir behaviors de Drupal, siempre implementa callbacks de detach que restauren completamente los elementos a su estado original. Usa el parámetro trigger para manejar diferentes escenarios de detach.
  • Habilita el módulo refreshless_debug durante el desarrollo para ver todos los eventos de RefreshLess registrados en la consola del navegador.
  • Para la precarga diferida de enlaces, agrega data-refreshless-lazy-preload a elementos contenedores en lugar de enlaces individuales. Excluye enlaces específicos con data-refreshless-lazy-preload="false".
  • El servicio kill switch (refreshless.kill_switch) puede usarse para deshabilitar RefreshLess para solicitudes específicas programáticamente - útil para páginas con requisitos únicos.
  • RefreshLess maneja automáticamente los cambios de tema activando una recarga completa. Diseña tu sitio con esto en mente si los usuarios cambian frecuentemente entre temas.
  • Las propiedades CSS personalizadas en la superposición de transición de página permiten tematización sin cambios de JavaScript. Sobrescribe las propiedades --refreshless-page-transition-* en tu tema.
  • El evento refreshless:before-render permite retrasar el renderizado con Promises - útil para implementar animaciones de salida personalizadas antes de que cambie el contenido.
  • Escucha refreshless:drupal-settings-update para reaccionar a cambios en drupalSettings, que proporciona objetos de configuraciones anteriores, nuevas y fusionadas.

Technical Details

Troubleshooting 8
La navegación de RefreshLess no funciona - las páginas se recargan completamente

Verifica que todos los parches requeridos del núcleo de Drupal estén aplicados. Ejecuta 'composer install' para asegurar que los parches estén aplicados. Verifica que la consola de JavaScript no muestre errores. Asegúrate de que el submódulo refreshless_turbo esté habilitado.

Error de compatibilidad con BigPipe durante la instalación

RefreshLess actualmente no es compatible con el módulo BigPipe. Desinstala BigPipe antes de instalar RefreshLess. Consulta el issue #3519784 para el progreso en la compatibilidad con BigPipe.

Los mensajes flash desaparecen después de la navegación

Esto se maneja automáticamente por el servicio de mensajería decorado. Si los mensajes aún desaparecen, asegúrate de que el módulo refreshless_turbo esté habilitado y la decoración del servicio de mensajería esté activa.

Los behaviors de JavaScript no se vinculan después de la navegación

Asegúrate de que tus behaviors tengan callbacks de detach apropiados que limpien completamente los cambios. Usa once() y once.remove() de la biblioteca @drupal/once. No almacenes referencias a elementos DOM fuera de los callbacks de behavior.

Problemas de especificidad CSS después de la navegación

RefreshLess mantiene el orden de las hojas de estilo para preservar la especificidad CSS. Si los problemas persisten, escucha el evento refreshless:stylesheets-merged y activa refreshless:sort-stylesheets si es necesario.

La página se recarga inesperadamente en lugar de usar RefreshLess

Revisa la consola del navegador para ver la razón de la recarga. Causas comunes: cambio de tema (ej. cambiar entre tema frontend y de administración), cambio de estado de agregación CSS/JS, cambio de hash de permisos de sesión. Estos son comportamientos esperados para asegurar consistencia.

El prefetching no funciona en ciertos enlaces

Algunos enlaces pueden estar excluidos del prefetching mediante drupalSettings.refreshless.prefetchExcludePaths o el atributo data-turbo-prefetch="false". Verifica si la ruta del enlace está en la lista de exclusión.

Las transiciones de página no aparecen

Asegúrate de que el submódulo refreshless_transitions esté habilitado. La superposición de transición depende de transiciones de opacidad CSS - no elimines la propiedad opacity. Verifica que el atributo data-refreshless-page-transition-state se esté estableciendo en el elemento html.

Security Notes 5
  • RefreshLess mantiene la protección CSRF de Drupal a través de tokens de tema almacenados en la cookie de estado de página.
  • La cookie de estado de página usa los atributos secure y sameSite:strict por defecto para mayor seguridad.
  • Los cambios en el hash de permisos de sesión activan una recarga completa de página para asegurar que los usuarios siempre vean contenido apropiado para sus permisos actuales.
  • El módulo de registro de depuración (refreshless_debug) está diseñado explícitamente para no exponer datos sensibles y es seguro para uso en producción.
  • Todas las solicitudes de RefreshLess incluyen un encabezado identificativo (x-refreshless-turbo) que puede usarse para identificación de solicitudes del lado del servidor y políticas de seguridad.