2012-06-28 9 views
9

Para mejorar el rendimiento/capacidad de respuesta de mi sitio web, he implementado una carga de página parcial utilizando AJAX, replaceState, pushState y un escuchador de estado emergente.Botón de retroceso de API de historial HTML5 con cargas de página parcial

Básicamente, almaceno la parte central de mi página (HTML) como mi objeto de estado en el historial. Cuando se hace clic en un enlace, solicito solo el bit central de la página del servidor (identificando estas solicitudes con un encabezado Accept diferente) y lo reemplazo por javascript. En estado popstate agarro la parte central anterior y la vuelvo a empujar hacia el dom.

Esto funciona sobre todo bien, sin embargo, he encontrado un problema en particular en el que estoy atascado. Es un poco complicado de explicar, así que mis disculpas si esto no está muy claro.

Hay un formulario de búsqueda en la mayoría de nuestras páginas. La carga de página parcial a través de ajax solo se realiza en solicitudes GET, y el formulario realiza una POST que da como resultado una carga de página completa.

Si navego el siguiente conjunto de páginas, que terminan en una página parcial malformación consiste en SOLO el contenido central, sin ninguno de los dom rodea:

Inicio en la página inicial (a través de página completa carga) - realiza una búsqueda (post-redirect-get)
le lleva a los resultados de búsqueda (a través de la carga de página completa) - a continuación, haga clic en Inicio
le devuelve a la página inicial (vía get dinámico) - hacer clic atrás del navegador
Buscar Resultados (del oyente popstate): haga clic en el navegador de nuevo
página de inicio con formato incorrecto mi.

Cuando aparece la página de inicio mal formada, mi escucha de popstate no está presente en absoluto.

Lo que que está sucediendo, es que la segunda carga (dinámica, parcial) de la página de inicio se almacena en caché por el navegador, y luego, cuando se produce vuelta la página completa, el navegador es simplemente mostrando la caché parcial respuesta en lugar de la página completa.

Para tratar de remediar esto he agregado un encabezado Vary: Accept a la respuesta para que los navegadores sepan que el contenido puede cambiar según el encabezado accept. También agregué Cache-Control max-age = 0, pragma no-cache, y una fecha de caducidad pasada al contenido cargado parcialmente para intentar obligar al navegador a no almacenar en caché esto, pero nada de esto lo resuelve.

Desafortunadamente, mi empresa no permite el tráfico externo a nuestros servidores de desarrollo, por lo que no puedo mostrarle el problema. He analizado varias preguntas similares aquí, pero ninguna de ellas parece ser la misma, y ​​las soluciones sugeridas tampoco parecen funcionar.

Si agrego un parámetro inútil (blah = blah) a mis solicitudes dinámicas GET, esto resuelve el problema. Sin embargo, este es un hack feo que prefiero no hacer. Parece que debería poder resolverse con encabezados, ya que creo que es un problema de almacenamiento en caché. ¿Alguien puede explicar lo que está pasando?

+0

Actualización rápida: los encabezados parecen resolver el problema en Firefox, pero persiste en Chrome y iOS Safari (¿problema con el webkit?) –

+0

Suena como un problema de almacenamiento en caché. Agregar un parámetro a las solicitudes GET dinámicas parece razonable, eso es lo que hace jquery-pjax. –

Respuesta

8

Eso es un problema de caché. Con el encabezado de respuesta Cache-Control establecido en no-cache o max-age=0, el problema no ocurre en FF (como usted dijo), pero persiste en Chrome.

El encabezado que funcionó para mí es Cache-Control: no-store. Eso no es implementado sistemáticamente por todos los navegadores (puede encontrar preguntas sobre cuál es la diferencia entre no-caché y no-tienda), pero también tiene el resultado esperado en Chrome.

1

Tuve un problema similar. Estoy construyendo un asistente basado en web y usando jquery ajax para cargar cada paso (ASP.NET MVC en el back-end).

La ruta inicial es algo así como/Preguntas/Show - que carga toda la página y muestra la primera pregunta (pregunta 0). Cuando el usuario hace clic en la imagen siguiente, hace un jquery .load() con la url/Questions/Save/0. Esto guarda la respuesta y devuelve una vista parcial con la siguiente pregunta. El siguiente guardado hace un jquery .load() con/Questions/Save/1 ...

Implementé History.js para que el usuario pueda ir hacia adelante y hacia atrás (¿adelante?). Almacena el número de pregunta en los datos de estado. Cuando detecta un cambio de estado (y el número de pregunta del estado es diferente de lo que está en la página), hace un jquery .load() para cargar la pregunta correcta.

Al principio estaba usando la misma ruta que cuando se carga la página inicial (/ Questions/Show/X donde X es el número de la pregunta). En la parte de atrás, detecté si se trataba de una solicitud de ajax y, de ser así, devolví una vista parcial en lugar de la vista completa. Aquí es donde el problema llegó similar al tuyo: di que estaba en la pregunta 3, volví y luego hacia adelante, luego fui a www.google.com y luego presioné el botón Atrás. Mostraba la pregunta 3 pero era la vista parcial, porque el navegador almacenaba en caché el parcial para esa ruta.

Mi solución era crear una ruta separada para la llamada ajax:/Questions/Load/X (utilizaba un código común en el back-end). Ahora con dos rutas diferentes (/ Preguntas/Show para no-ajax y/Questions/Load para ajax), el navegador muestra la página completa correctamente en la situación anterior.

Así que tal vez una solución similar funcione para usted ... es decir, dos rutas diferentes para su página de inicio: una para la página completa y otra para una parcial. Espero que ayude.

0

Cuando se hace clic en un vínculo solicito simplemente el bit central de la página del servidor (la identificación de estas peticiones con una diferente Aceptar cabecera) y reemplazarlo con javascript.

Impresionante. Esa es la forma RESTANTE de hacerlo. Pero queda una cosa por hacer para que funcione: agregue un encabezado Vary a la respuesta.

Vary: Accept 

Eso le dice al navegador que una solicitud con un encabezado Accept diferente puede obtener una respuesta diferente. Debido a que las dos solicitudes usan diferentes encabezados Aceptar, el navegador (y los proxies de almacenamiento en caché) almacenarán en caché las respuestas por separado.

A diferencia del ajuste Cache-Control: no-store, esto todavía le permitirá usar el almacenamiento en caché.

Cuestiones relacionadas