8

I am firing an XHR from JS code. This render-blocking XHR is fired on every page load, so I want to fetch it early in page's lifecycle, in parallel with JS and CSS resources. Inside my index.html, I'll add the following code:

<head>
  <link rel="stylesheet" href="style.css">
  <link rel="preload" as="fetch" href="/xhr-to-be-fetched-early">
</head>

The XHR request needs some custom headers such as authorization & Accept. Is there any way to add these headers to link tag, either inside HTML itself or via JS? Or is it impossible to cache such requests?

Ayush
  • 93
  • 2
  • 14

3 Answers3

8

You cannot truly add headers to a <link> tag, but you can stop the page from loading anything until the resource is fetched.

See something like this:

const promiseOfSomeData = fetch("URL.com", { 
    // This is where you set the headers
    headers: {
        'X-My-Cool-Header': 'here'
    }
}).then(data => {
    return data;
});
window.onload = async () => {
    let someData = await promiseOfSomeJsonData;
    console.log(someData)
};

How can I make "onload" waiting for "fetch" complete?

divinelemon
  • 1,925
  • 2
  • 23
  • Thanks! This is an interesting solution. For my use case, the XHR request needs to be fired from a different JS file. That can be done by storing promise in a global variable. – Ayush Mar 25 '21 at 10:17
1

you can't add custom headers in the link request; when you use as to specify the type of content, browsers will automatically apply the correct headers based on the content type, but you don't have access to this lifecycle.

you could use a <script async></script> instead, https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-async, and perform the fetch with extra headers. It will be executed in parallel with other resources of the page.

oieduardorabelo
  • 2,687
  • 18
  • 21
  • Manually firing an XHR doesn't seem to help with preloading it. I mean, if I fire the same XHR from application code, it is taking the same amount of time. It isn't instantaneous as is expected from cached responses. I checked the headers for both requests are exactly the same. Maybe it's because of Cache-control: no-cache header. From all this, I guess preload is more suited for my use case, and I don't have any option but to match the headers set by preload HTML tag. – Ayush Mar 18 '21 at 07:36
1

A unique situation, although, I have an idea popping in my mind that says how about you replace your preload link with a small JS snippet that requests the data using XHR, or fetch, or whatever method you prefer. Replace this:

<link rel="preload" as="fetch" href="/xhr-to-be-fetched-early">

with this:

<script async>
    fetch('target-url', {
        headers: {
            'Content-Type': 'application/json',
            //add headers here
        }
    })
    .then(response => response.json())
    .then(response => console.log("Preloaded", response))
</script>

Hope it helps, see more about fetch here.

async attribute in the script tag isn't necessary but it'll help reduce the load times if the data is kinda large.

Kashan Ahmad
  • 165
  • 5