9

I am fetching blade html using XHR GET and trying to cache it so that it does not need to go to server to download it every time. Here is my code.

But this does not work and always goes to server.

$.ajax({
    method: "GET",
    url:    "{!! route('SendMessageForm') !!}",
    cache:  true,
    async:  true,
    beforeSend: function(xhr, opts) {
        $('#MessageModal').html(processingImageUrl);
    },
    success: function(result) {
        $('#MessageModal').html(result);
        PopulateActiveUsers();
    },
    error: function() {
    }
});

Controller

public function SendMessageForm() {
    return View("Chat.SendMessage");
}

Header Info

enter image description here

Pankaj
  • 9,749
  • 32
  • 139
  • 283
  • can you show your controller method that process the SendMessageForm route? – elegisandi Jul 31 '17 at 06:30
  • Controller Info is added. Please let me know if you need more details. – Pankaj Aug 01 '17 at 03:11
  • 1
    i think for some reason, laravel is not allowing response caching by default. I don't think this is a solution but still works - just return `response()->view('Chat.SendMessage')->header('Cache-control', 'public, max-age=31536000');`. you can set values you need. – elegisandi Aug 01 '17 at 04:55

3 Answers3

3

It is not the fault of jQuery actually. Per the documentation:

Setting cache to false will only work correctly with HEAD and GET requests. It works by appending "_={timestamp}" to the GET parameters.

So, it actually forces browser to load new copy of the requested resource, by tricking it by changing the URL. So browser thinks that it is a new request, and then loads it from the server again. It doesn't actually caches the response somewhere.

Caching the responses is browser's part, and to play this role, it needs appropriate cache headers. I can see, your response doesn't contain appropriate headers as pointed out by @elegisandi in the comments. So there are two possible solutions to this problem.

Add cache headers to server response

You will have to modify the response headers, so that the browser can cache the response. This question and its answers can help you setting up that.

Manually cache the response

You can manually cache the response of the requests in a JavaScript object. But beware, you'll manually have to expire these. Here is an example of how to do this:

var cache = {};

function ajaxCall(options) {
  if (!cache[options.url]) {
    cache[options.url] = $.ajax(options);
  }

  return cache[options.url];
}

// In your code
ajaxCall({
  method: "GET",
  url: "{!! route('SendMessageForm') !!}",
  beforeSend: function (xhr, opts) {
    $('#MessageModal').html(processingImageUrl);
  }
})
.then(function (result) {
  $('#MessageModal').html(result);
  PopulateActiveUsers();
});

The second time you fire a request to the same URL, it will actually return the response from the cache. Further, we can customise the ajaxCall function so that it checks the request method as well.

31piy
  • 23,323
  • 6
  • 47
  • 67
1

The jQuery ajax cache option (http://api.jquery.com/jquery.ajax/) just controls if the browser can use the normal caching strategies. It defaults to true.

To actually make use of caching here, the server (your Laravel application) should tell the client that it can cache the return value.

Right now (Cache-Control: no-cache, private) it is explicitly forbidding the client from caching the result. The Cache-Control header is very versatile (see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) but you could for instance return a value of Cache-Control: public to tell the client that the resource is public and can be cached always.

You can do this in your controller action like so:

public function SendMessageForm() {
    return response()
               ->view("Chat.SendMessage")
               ->header('Cache-Control', 'public');
}
Tim van Dalen
  • 1,470
  • 3
  • 21
  • 41
1

You need to change response behavior in server side:

return response()
            ->view('Chat.SendMessage')
            ->header('Cache-Control', 'public, max-age=300');
Govind Samrow
  • 9,981
  • 13
  • 53
  • 90