Search code examples
javascriptcloudflarehttp2server-pushcloudflare-workers

HTTP/2 Server Push not working for JavaScript files


I am trying to implement HTTP/2 Server Push through CloudFlare Workers using below code:

let mainScript='main-es2015.e66dc0bc532401d980dc.js';
response.headers.append("Link", "</"+mainScript+">; rel=preload; as=script;");

I have also tried adding crossorigin

response.headers.append("Link", "</"+mainScript+">; rel=preload; as=script; crossorigin;");

But its not working.

In first case, the Developer console does show that file is being Pushed from the CloudFlare server along with html response. but the browser doesnt use that file and makes a duplicate request to download the file again.

In second case, the Developer console shows that the browser does honor the preloaded header, but the contents of the file are not pushed from Cloudflare server and the browser has to make seperate request to pull javascript file, although it makes the request immediately after receiving the html file.

What I want is the cloudflare server to push the file and browser to use that pushed file without making a duplicate request?

Surprisingly, below code works perfectly for css files:

  response.headers.append("Link", "</styles.1d228f78d240e617dd5e.css>; rel=preload; as=style;");

but doesnt work for any other content like javascript font files, images etc.

Can anyone please guide what am I missing here?


Solution

  • As discussed offline you had two issues:

    Your fonts were being double downloaded instead of using the Pushed versions

    Fonts need the crossorigin attribute in the link header or the push will be ignored. See this answer: HTTP2 pushed webfonts not used

    However, even when you added that it appears that Cloudflare stopped pushing so maybe they don't support that.

    Most of your JavaScript files were similarly being double downloaded instead of using the Pushed versions

    This is because you were specifying them as modules:

    <script src="main-es2015.e66dc0bc532401d980dc.js" type="module"></script>
    

    Instead of as simple script files:

    <script src="main-es2015.e66dc0bc532401d980dc.js"></script>
    

    The ones that were successfully pushed, were not defined as modules. Changing the link header to as="module" seems to work in Chrome, but this is not in the preload specification, and looks like an alternative is under discussion so not sure how supported that is or if it will continue to be supported.