Closed d3473r closed 1 month ago
Is this strictly true for all SPAs? Mine work without this. The example here should be as minimal as possible, but in the new docs we can expand the examples.
Afaik as soon as you do try_files {path} /index.html
you should explicitly set a cache-control index.html, see vercel https://github.com/vercel/serve/issues/258, aws (they recommend 60 sec for index.html) https://aws.amazon.com/blogs/networking-and-content-delivery/host-single-page-applications-spa-with-tiered-ttls-on-cloudfront-and-s3/ or codecentric https://www.codecentric.de/wissens-hub/blog/deployment-configurable-single-page-application
But you are right, maybe a second example which talks about this issue would be better than modifying the minimal example.
One then could also add a long cache time (public,max-age=31536000,immutable
) for css
and js
files as they are fingerprinted and have a different name when the application.is rebuild
Can you point me to the new docs, then i can add this example there
Oh I haven't got them ready yet. 😅 that's on me, I'm a bit behind lately.
I reworked this, I moved this below the other two examples and added an explanation. Thanks for the idea!
Hi @francislavoie, thank you for merging the example!
But i don't understand the explanation you added to it.
The reason for adding the header Cache-Control "public, max-age=0, must-revalidate"
is not to instructs clients to cache the index.html
, rather its to instruct clients to explicitly not to cache it.
To give you an example, if i do a angular build (or any other spa build that uses fingerprinting), you'll get this index.html
:
<!DOCTYPE html>
<html lang="en" data-critters-container>
<head>
<meta charset="utf-8" />
<title>CaddySpa</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<link rel="stylesheet" href="styles-5INURTSO.css" />
</head>
<body>
<app-root></app-root>
<script src="polyfills-FFHMD2TL.js" type="module"></script>
<script src="main-ITZNYXFD.js" type="module"></script>
</body>
</html>
As you can see the css
and js
files are fingerprinted: styles-5INURTSO.css
, polyfills-FFHMD2TL.js
and main-ITZNYXFD.js
If i now change some javascript and build the spa again I'll get this index.html
:
<!DOCTYPE html>
<html lang="en" data-critters-container>
<head>
<meta charset="utf-8" />
<title>CaddySpa</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<link rel="stylesheet" href="styles-5INURTSO.css" />
</head>
<body>
<app-root></app-root>
<script src="polyfills-FFHMD2TL.js" type="module"></script>
<script src="main-7MRHVRTZ.js" type="module"></script>
</body>
</html>
You can see now that the main.js got a new fingerprint and is now main-7MRHVRTZ.js
.
The browser will now load this new js file an the spa is updated.
Now comes the problem when the index.html
is cached:
The browser will download or use already cached outdated fingerprinted css and js files and serve a old spa version.
That means for css and js files you can use a long cache time (even one year) as they have unique fingerprinted names, but the index.html
you can never cache, as it will change for every build of the spa.
Ah okay, my mistake. If you want to do a follow-up PR to adjust the wording, that would be great 👍
Edit the SPA example
Add the Cache-Control "public,max-age=0,must-revalidate" for index.html header to the SPA example.
In SPAs the index.html must be prevented from being cached, in the index.html the (fingerprinted) javascript and css file are referenced (these can be cached becaused they get a new random suffix everytime they are built)