paulgreg
paulgreg

Reputation: 18933

Why are preload link not working for JSON requests ?

The JavaScript on my website loads several JSON to initialize itself.

I would like to preload them so, when the JavaScript will launch an Ajax request on it, they will be loaded instantaneously.

A new link tag exists for that.

I tried to use it to load a JSON like that :

<link rel="preload" href="/test.json">

However, Chrome seems to load it twice and present a warning in the console :

The resources test.json was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it wasn't preloaded for nothing.

So it seems that preload doesn’t work for JSON. Indeed, I haven’t found reference to JSON in the specification.

Is that correct or am I doing it wrong ?

Upvotes: 20

Views: 17231

Answers (9)

Eugene Fidelin
Eugene Fidelin

Reputation: 2329

Here is the approach that works both in Chrome and Safari.

<link rel="preload" as="fetch" href="/data.json">
fetch('/data.json', {
    method: 'GET',
    credentials: 'include',
    mode: 'no-cors',
})

This answer contains more details and explanation why and how does it work https://stackoverflow.com/a/63814972/1387163

Upvotes: 2

user
user

Reputation: 25798

According to the Chrome bug mentioned in the comments, preload doesn't work when you have responseType = 'blob'.

The workaround is to set responseType = 'arraybuffer' and then in onload convert to blob manually using var blob = new Blob([xhr.response], {type: xhr.getResponseHeader("Content-Type")});

Upvotes: 0

keithl8041
keithl8041

Reputation: 2413

I tried so many variations on the allowed values on https://w3c.github.io/preload/#as-attribute but the only thing that worked for me to fetch JSON data properly was removing the type and as directives completely and relying on the browser to figure it out. Works in the latest Chrome but I guess it might change as browser behaviour changes.

Developer tools image showing XHR push

Upvotes: 0

J.P. Duvet
J.P. Duvet

Reputation: 690

According to https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content , you have to add as="fetch" for JSON files. So your code becomes

<link rel="preload" href="/test.json" as="fetch">

It's supported by all modern browsers and you get a warning message if this resource is not used within a few seconds because it is counterproductive to "preload" it in a such case (delay, double load etc.)

It's different from <link rel="prefetch" ...> which is to anticipate future navigation and not supported widely.

A Chrome illustrated article about this: https://medium.com/reloading/preload-prefetch-and-priorities-in-chrome-776165961bbf

Upvotes: 24

makkabi
makkabi

Reputation: 639

You have to add not only as="fetch", but (based on this comment) also crossorigin="anonymous". This should work:

<link rel="preload" href="/test.json" as="fetch" crossorigin="anonymous">

Upvotes: 9

8020erwin
8020erwin

Reputation: 1

Try as="object". Seems to work for me:

<link rel="preload" href="/test.json" as="object">

Upvotes: -5

Dan
Dan

Reputation: 13190

If you have the same problem as me, your response is probably being sent with Vary: Accept, the preload request is sent with Accept: */*, and the fetch/xhr request is being made with Accept: application/json.

It seems like the preload Accept: behavior can't be changed (sigh), so you'll have to either remove the Vary: Accept, or make the fetch/xhr request with a matching Accept: header.

Upvotes: 11

torno
torno

Reputation: 1232

Turns out there has been a bug in Chrome for using the fetch API combined with rel=preload here. I solved this by using XMLHttpRequest instead.

Even though it seems to have been fixed in Chrome 62 it seems like I could still reproduce this on my Chrome 63.

Upvotes: 3

Seb
Seb

Reputation: 25157

Try as="xhr". Seems to be working for me in Chrome when I do a server push - that's not exactly the same as the HTML tag but if you are getting that resources via Ajax / XmlHttpRequest, this might fix it.

Upvotes: -3

Related Questions