I'd like to use prefetching (All) or prerendering (Chrome only) to speed up my website performance. It pre-loads websites to instantly load them when navigating to them. Google does it for its #1 Searchresults.

<link rel="prerender" href="{{ url('mysubpage') }}"> <link rel="prefetch" href="{{ url('mysubpage') }}">


The browser is initializing a prefetch as I can see in my DevTools, but when visiting the page, there is still another normal page load happening instead of using the cached version. I wonder if this is because Craft CMS is returning the HTTP Header

Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0

on every response? Does this prevent the prefetching? Does it make sense to disable this headers? I didn't found any mention on cache headers being a problem when using <link rel="prefetch">

Thanks for some insights.


2 Answers 2


Per Brad's answer, PHP is setting the cache control headers on the start of a new user session.

If you want to override this, Craft provides the {% header %} tag where you can set your own headers. Whether or not that affects Chrome, I couldn't say.

One other thing to note is cookies. This page mentions "prerendered or prefetched [pages] may set and read their own cookies as if you had visited them before -- even if you don’t visit the prerendered or prefetched pages after all" which seems to imply it'll use the current page's headers for prefetch requests.

If you do any cookie-based server-side tracking or analytics with Craft, that could wreck a little havoc. (Say your funnel is "load XXX page and then load the contact page." You'd be wondering why people visited the contact page but never filled it out.)

If you use prerender, it looks like Chrome will actually execute any javascript on the page as well, which would also defeat any JS based analytics packages.) Scary.

(For what it's worth, I haven't tested any of these techniques at all but it would be interesting to see what kind of mainstream traction they receive. I can see for a web app it might be more useful.)


Thank you.

It seems that the fetching only works if the returned page is cachable, so I override the headers with the {% header %} tag.

{% set expiry = now|date_modify('+2 minute') %}
{% header "Cache-Control: max-age=" ~ (expiry.timestamp - now.timestamp) %}
{% header "Pragma: cache" %}
{% header "Expires: " ~ expiry|date('D, d M Y H:i:s', 'GMT') ~ " GMT" %}

I now set this on every craft template (respectively on the main layout template) and cache it for two minutes. This gives a lot of performance boost and and allows any kind of prefetching. And with two minutes, outdated content won't be too much of a problem.

To deal with the statistic problem:

Firefox sets a HTTP Header X-moz: prefetch on all prefetch requests, which can be used to distinguish prefetch requests from real site views.

Chrome sets a HTTP Header Purpose:prefetch. I didn't check how IE is dealing with prefetch requests.

As prefetching is actually supported by FF, Chrome and IE >=11, I think it is a very useful, performance boosting optimization. It should be used sparely and wisely though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.