Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PJAX: Problems with back button

Some our links are wrapped by PJAX. When a user clicks on a PJAX link the server returns only the required part of the HTML.

If I do the following:

  1. Click PJAX link
  2. Click simple link
  3. Press back button

the browser will display content that was returned by the PJAX request. The HTML will be broken because it's only part of the HTML to be displayed (check this question).

We have tried to fix this by not caching PJAX responses (Cache-Control header). This fixed our problem but raised another one: When the user presses the back button, WebKit (Chrome 20.0) loads full content from server, then fires popstate event that causes an unnecessary PJAX request.

Is it possible to recreate correct back button behaviour?

like image 543
fedor.belov Avatar asked Jul 26 '12 06:07

fedor.belov


2 Answers

To make the Browser aware of the different versions of the HTTP resources depending on the request-headers I added a Vary http header.

Using Vary, you don't need to send no-cache headers anymore and therefore get your page fast again.

In PHP this would look like:

header("Vary: X-PJAX");

Since we sometimes use 3 representations per URL (regular http, pjax and ajax) - because migrate to a PJAX approach in a already sometimes ajaxified app - we actually use:

header("Vary: X-PJAX,X-Requested-With");

In case you need to support old IE (older than IE9) versions you need to make sure that the Vary header is stripped by your webserver, because otherweise old IE will disable caching for all your resources which provide a Vary header.

This could be achieved by the following setting in your .htaccess/vhost config:

BrowserMatch "MSIE" force-no-vary

Edit: Underlying chrome bug, https://code.google.com/p/chromium/issues/detail?id=94369

like image 197
staabm Avatar answered Nov 18 '22 14:11

staabm


This all depends from server caching settings. You browser caches the AJAX response from server and when you click Back button it uses cached version.

To prevent caching set following headers on server:

'Cache-Control' => 'no-cache, no-store, max-age=0, must-revalidate'
'Pragma' => 'no-cache'

If you are using Rails, then definitely try Wiselinks https://github.com/igor-alexandrov/wiselinks. It is a a Swiss Army knife for browser state management. Here are some details: http://igor-alexandrov.github.io/blog/2013/07/11/the-way-to-wiselinks-1-dot-0/.

like image 38
Igor Alexandrov Avatar answered Nov 18 '22 14:11

Igor Alexandrov