I'm deploying a Single Page Application (SPA) on AWS S3 and CloudFront, and I'm facing an issue with caching that leads to outdated versions of the application being loaded.
Browsers like Chrome and Edge:
index.html
directly from the disk cache without making a HEAD
or GET
request to check for updates.index.html
file doesn't have the correct Cache-Control
headers.index.html
) are loaded, causing the application to run an older version.Redirect Configuration:
index.html
is served.index.html
.Requirements:
index.html
: Should always check for updates. Headers like Cache-Control: no-cache
or max-age=0, must-revalidate
should force the browser to revalidate it..js
, .css
, etc.): These are hashed (e.g., main.abc123.js
), so they can be cached long-term (Cache-Control: public, max-age=31536000, immutable
).index.html
and versioned assets (js/css files with hashes)./*
). No cache-control header modification.index.html
(lambda does not trigger here i think).Viewer response
lambda@edge to add Cache-Control: no-cache
for text/html
files. Added Viewer request
lambda@edge, to redirect anything without extension (not asset) to index.html. Works but i think there should be a better solution.index.html
but keeps static assets cached long-term?Thx for help!
I'm deploying a Single Page Application (SPA) on AWS S3 and CloudFront, and I'm facing an issue with caching that leads to outdated versions of the application being loaded.
Browsers like Chrome and Edge:
index.html
directly from the disk cache without making a HEAD
or GET
request to check for updates.index.html
file doesn't have the correct Cache-Control
headers.index.html
) are loaded, causing the application to run an older version.Redirect Configuration:
index.html
is served.index.html
.Requirements:
index.html
: Should always check for updates. Headers like Cache-Control: no-cache
or max-age=0, must-revalidate
should force the browser to revalidate it..js
, .css
, etc.): These are hashed (e.g., main.abc123.js
), so they can be cached long-term (Cache-Control: public, max-age=31536000, immutable
).index.html
and versioned assets (js/css files with hashes)./*
). No cache-control header modification.index.html
(lambda does not trigger here i think).Viewer response
lambda@edge to add Cache-Control: no-cache
for text/html
files. Added Viewer request
lambda@edge, to redirect anything without extension (not asset) to index.html. Works but i think there should be a better solution.index.html
but keeps static assets cached long-term?Thx for help!
Is it true that Chrome/Edge bookmarks skip checking for updates (e.g., ETag) if no Cache-Control header is set and load files directly from disk cache?
As far as I know, Cache-Control supersedes ETag. Cache-Control max-age tells the browser not even to attempt checking for ETag. However once the content is stale (as determined by the max-age), browsers can request the servers by providing its cached ETag value. This helps the server because if the ETag has not changed, the server may choose not to return the full-sized content and instead just say "304 Not Modified".
Does the 403 → 200 error response affect caching behavior, and if so, how can I improve it?
It does affect caching behavior, but isn't it a single page application? In other words, index.html is always involved anyway. And the caching is still subject to Cache Control headers. So you can still use max-age. I don't think this is an issue.
What’s the best caching configuration to ensure the app always checks for updates (e.g., ETag/header) for index.html but keeps static assets cached long-term?
It seems like you already know this, use Cache Control headers to control browser behavior. You can configure different max-age for different assets. And on the CloudFront side, just run invalidate cache whenever you have an updated version of index.html.