Desafíos y soluciones para compilar apps web progresivas en sitios de varios orígenes
Contexto
En el pasado, usar arquitecturas de varios orígenes tenía algunas ventajas, pero para las apps web progresivas, ese enfoque presenta muchos desafíos. En particular, la política de mismo origen impone restricciones para compartir elementos como los trabajadores del servicio y las cachés, los permisos y para lograr una experiencia independiente en varios orígenes. En este artículo, se describirán los usos adecuados y no adecuados de los múltiples orígenes, y se explicarán los desafíos y las soluciones para compilar apps web progresivas en sitios de varios orígenes.
Usos correctos y incorrectos de varios orígenes
Existen algunos motivos legítimos para que los sitios empleen una arquitectura de varios orígenes, principalmente relacionados con la entrega de un conjunto independiente de aplicaciones web o la creación de experiencias completamente aisladas entre sí. También hay usos que se deben evitar.
Ventajas
Primero, veamos los motivos útiles:
Localización o idioma: Usa un dominio de nivel superior de código de país para separar los sitios que se publicarán en diferentes países (p.ej.,
https://www.google.com.ar
) o usa subdominios para dividir los sitios segmentados para diferentes ubicaciones (p.ej.:https://newyork.craigslist.org
) o para ofrecer contenido en un idioma específico (p.ej.,https://en.wikipedia.org
).Aplicaciones web independientes: Usan diferentes subdominios para proporcionar experiencias cuyo propósito difiere considerablemente del sitio en el origen principal. Por ejemplo, en un sitio de noticias, la app web de crucigramas se podría entregar intencionalmente desde
https://crosswords.example.com
, instalarse y usarse como una AWP independiente, sin tener que compartir recursos ni funciones con el sitio web principal.
Desventajas
Si no haces ninguna de estas acciones, es probable que usar una arquitectura de varios orígenes sea una desventaja cuando crees apps web progresivas.
A pesar de esto, muchos sitios siguen estructurados de esta manera sin motivo alguno o por razones "heredadas". Un ejemplo es usar subdominios para separar de forma arbitraria partes de un sitio que deberían ser parte de una experiencia unificada.
Por ejemplo, se desaconsejan los siguientes patrones:
Secciones del sitio: Separa las diferentes secciones de un sitio en subdominios. En los sitios de noticias, no es raro ver la página principal en
https://www.example.com
, mientras que la sección de deportes se encuentra enhttps://sports.example.com
, la de política enhttps://politics.example.com
, etcétera. En el caso de un sitio de comercio electrónico, usa algo comohttps://category.example.com
para las categorías de productos,https://product.example.com
para las páginas de productos, etcétera.Flujo de usuarios: Otro enfoque que no se recomienda es separar diferentes partes más pequeñas del sitio, como las páginas para los flujos de acceso o compra en subdominios. Por ejemplo, usa
https://login.example.com
yhttps://checkout.example.com
.
En los casos en que no es posible migrar a un solo origen, a continuación, se incluye una lista de desafíos y (siempre que sea posible) soluciones alternativas que se pueden considerar cuando se compilan apps web progresivas.
Desafíos y soluciones para las AWP en diferentes orígenes
Cuando se compila un sitio web en varios orígenes, proporcionar una experiencia de PWA unificada es un desafío, principalmente debido a la política de mismo origen, que impone una serie de restricciones. Analicemos cada una de ellas.
Service workers
El origen de la URL de la secuencia de comandos del trabajador de servicio debe ser el mismo que el origen de la página que llama a register(). Esto significa que, por ejemplo, una página en https://www.example.com
no puede llamar a register()
con una URL de trabajador de servicio en https://section.example.com
.
Otra consideración es que un service worker solo puede controlar las páginas alojadas en el origen y la ruta a la que pertenece. Esto significa que, si el service worker se aloja en https://www.example.com
, solo puede controlar las URLs de ese origen (según la ruta definida en el parámetro de alcance), pero no controlará ninguna página en otros subdominios, como, por ejemplo, los de https://section.example.com
.
En este caso, la única solución alternativa es usar varios trabajadores del servicio (uno por origen).
Almacenamiento en caché
El objeto Cache, IndexedDB y localStorage también se limitan a un solo origen. Esto significa que no es posible acceder a las cachés que pertenecen a https://www.example.com
, por ejemplo, desde https://www.section.example.com
.
Estas son algunas acciones que puedes realizar para administrar las cachés correctamente en situaciones como esta:
Aprovecha el almacenamiento en caché del navegador: Siempre se recomienda usar las prácticas recomendadas tradicionales de almacenamiento en caché del navegador. Esta técnica proporciona el beneficio adicional de reutilizar recursos almacenados en caché en todos los orígenes, lo que no se puede hacer con la caché del trabajador del servicio. Para conocer las prácticas recomendadas sobre cómo usar la caché HTTP con los trabajadores del servicio, consulta esta publicación.
Mantén la instalación del trabajador de servicio liviana: Si administras varios trabajadores de servicio, evita que los usuarios paguen un gran costo de instalación cada vez que navegan a un origen nuevo. En otras palabras, solo almacena en caché los recursos que son absolutamente necesarios.
Permisos
Los permisos también se limitan a los orígenes. Esto significa que, si un usuario otorga un permiso determinado al origen https://section.example.com
, no se transferirá a otros orígenes, como https://www.example.com
.
Como no hay forma de compartir permisos entre orígenes, la única solución es solicitar permiso en cada subdominio en el que se requiera una función determinada (p.ej., la ubicación). En el caso de los mensajes push web, puedes mantener una cookie para hacer un seguimiento de si el usuario aceptó el permiso en otro subdominio y evitar solicitarlo nuevamente.
Instalación
Para instalar una AWP, cada origen debe tener su propio manifiesto con un start_url
que sea relativo a sí mismo. Esto significa que un usuario que reciba el mensaje de instalación en un origen determinado (es decir, https://section.example.com
) no podrá instalar la AWP con un start_url
en uno diferente (es decir, https://www.example.com
). En otras palabras, los usuarios que reciban el mensaje de instalación en un subdominio solo podrán instalar AWP para las subpáginas, no para la URL principal de la app.
También existe el problema de que el mismo usuario podría recibir varias solicitudes de instalación cuando navega por el sitio, si cada subdominio cumple con los criterios de instalación y le solicita al usuario que instale la AWP.
Para mitigar este problema, puedes asegurarte de que el mensaje se muestre solo en el origen principal. Cuando un usuario visita un subdominio que cumple con los criterios de instalación, sucede lo siguiente:
- Escucha el evento
beforeinstallprompt
. - Evita que aparezca el mensaje llamando a
event.preventDefault()
.
De esta manera, te aseguras de que el mensaje no se muestre en partes no deseadas del sitio, mientras puedes seguir mostrándolo, por ejemplo, en el origen principal (p.ej., la página principal).
Modo independiente
Mientras navegas en una ventana independiente, el navegador se comportará de manera diferente cuando el usuario salga del alcance establecido por el manifiesto de la AWP. El comportamiento depende de cada versión y proveedor del navegador. Por ejemplo, las versiones más recientes de Chrome abren una pestaña personalizada de Chrome cuando un usuario sale del alcance en el modo independiente.
En la mayoría de los casos, no hay una solución para esto, pero se puede aplicar una solución alternativa para partes pequeñas de la experiencia que se alojan en subdominios (por ejemplo, flujos de trabajo de acceso):
- La URL nueva,
https://login.example.com
, podría abrirse dentro de un iframe de pantalla completa. - Una vez que se complete la tarea dentro del iframe (por ejemplo, el proceso de acceso), se puede usar postMessage() para pasar la información resultante del iframe a la página superior.
- Como paso final, una vez que la página principal recibe el mensaje, se pueden anular los objetos de escucha y, por último, quitar el iframe del DOM.
Conclusión
La política del mismo origen impone muchas restricciones para los sitios creados en varios orígenes que desean lograr una experiencia de AWP coherente. Por ese motivo, para proporcionar la mejor experiencia a los usuarios, te recomendamos que no dividas los sitios en diferentes orígenes.
En el caso de los sitios existentes que ya se compilaron de esta manera, puede ser un desafío hacer que las AWP de varios orígenes funcionen correctamente, pero exploramos algunas posibles soluciones. Cada uno puede tener sus ventajas y desventajas, por lo que debes usar tu criterio para decidir qué enfoque adoptar en tu sitio web.
Cuando evalúes una estrategia a largo plazo o un rediseño del sitio, considera migrar a un solo origen, a menos que haya un motivo importante para mantener la arquitectura de varios orígenes.
Muchas gracias por sus revisiones técnicas y sugerencias: Penny Mclachlan, Paul Covell, Dominick Ng, Alberto Medina, Pete LePage, Joe Medley, Cheney Tsai, Martin Schierle y Andre Bandarra.