When using external js files, browsers can be forced to reload the files. See here.
Recently, I've found out that INLINE scripts are also cached, at least in Chrome, version 80.0.3987.132, example of snippet:
<html>
<head>
<script>alert("I am cached!");</script>
</head>
<body>
<script>alert("Me too!");</script>
</body>
</html>
What's the way of refreshing inline scripts?
Update 1: I do have to mention that the webserver returning the content is using HTTP 2.0
Update 2: A solution that works is to have an auxiliary script as base and when the page loads get the "real" script content through ajax or websocket then append it to head like so:
function addScript(content){
let s = document.createElement('script');
s.innerHTML = content;
document.head.appendChild(s);
}
This does the job but its not optimal as it needs more requests than necessary.
Update 3: Headers sent from backend neither seem to work, using these headers:
Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") // HTTP 1.1.
Header().Set("Pragma", "no-cache") // HTTP 1.0.
Header().Set("Expires", "0") // Proxies.
Update 4: As per Jinxmcg's answer, the doc /blog/code-caching-for-devs Don’t change URLs
mentions:
we may one day decide to associate caches with the source text rather than source URL, and this advice will no longer be valid.
Probably that day has e and is also applied to inline scripts.
Thank you everyone for participating
Final Solution (works at least under my circumstances):
1 Backend headers:
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate, max-age=0") // HTTP 1.1.
w.Header().Set("Pragma", "no-cache") // HTTP 1.0.
w.Header().Set("Expires", "0") // Proxies.
2 Random string in HTML, JS and CSS, example:
<html>
<head>
<style>
--cache-color: #8528cc; //Random hex color generated by backend
</style>
<script>
console.log("<?php echo date(); ?>");
alert("I am cached!");
</script>
</head>
<body>
<div>Hidden DIV with a random value: <?php echo date(); ?></div>
<script>
console.log("<?php echo date(); ?>");
alert("Me too!");
</script>
</body>
</html>
When using external js files, browsers can be forced to reload the files. See here.
Recently, I've found out that INLINE scripts are also cached, at least in Chrome, version 80.0.3987.132, example of snippet:
<html>
<head>
<script>alert("I am cached!");</script>
</head>
<body>
<script>alert("Me too!");</script>
</body>
</html>
What's the way of refreshing inline scripts?
Update 1: I do have to mention that the webserver returning the content is using HTTP 2.0
Update 2: A solution that works is to have an auxiliary script as base and when the page loads get the "real" script content through ajax or websocket then append it to head like so:
function addScript(content){
let s = document.createElement('script');
s.innerHTML = content;
document.head.appendChild(s);
}
This does the job but its not optimal as it needs more requests than necessary.
Update 3: Headers sent from backend neither seem to work, using these headers:
Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") // HTTP 1.1.
Header().Set("Pragma", "no-cache") // HTTP 1.0.
Header().Set("Expires", "0") // Proxies.
Update 4: As per Jinxmcg's answer, the doc https://v8.dev/blog/code-caching-for-devs Don’t change URLs
mentions:
we may one day decide to associate caches with the source text rather than source URL, and this advice will no longer be valid.
Probably that day has e and is also applied to inline scripts.
Thank you everyone for participating
Final Solution (works at least under my circumstances):
1 Backend headers:
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate, max-age=0") // HTTP 1.1.
w.Header().Set("Pragma", "no-cache") // HTTP 1.0.
w.Header().Set("Expires", "0") // Proxies.
2 Random string in HTML, JS and CSS, example:
<html>
<head>
<style>
--cache-color: #8528cc; //Random hex color generated by backend
</style>
<script>
console.log("<?php echo date(); ?>");
alert("I am cached!");
</script>
</head>
<body>
<div>Hidden DIV with a random value: <?php echo date(); ?></div>
<script>
console.log("<?php echo date(); ?>");
alert("Me too!");
</script>
</body>
</html>
Share
Improve this question
edited Mar 24, 2020 at 14:55
Alpha2k
asked Mar 15, 2020 at 11:24
Alpha2kAlpha2k
2,2417 gold badges43 silver badges67 bronze badges
13
- @JonSkeet got any idea how to handle this? :P – Alpha2k Commented Mar 17, 2020 at 18:37
- 2 Your example will always say "I am cached!" and "Me too" regardless of cache. Can you post a relevant example? – Jinxmcg Commented Mar 18, 2020 at 10:08
- 1 the test would be to append a random number to the strings and check if it changes between reloads and add it in the HTML too and see if it changes. As I written in my answer I highly doubt you're hitting a inline js cache, I think a full page cache it is what you hit and you can fix that with appropriate caching headers. – Jinxmcg Commented Mar 20, 2020 at 10:00
- 1 Ok. This seems to be Server caching rather than Browser caching. Can you few cURL tests? and see if the content changes between cURL requests? because it might be that the server it is actually serving the same content from a local cache. – Jinxmcg Commented Mar 21, 2020 at 15:43
- 1 Do not worry, I am not dissapointed :) I was just trying to eliminate all the possible causes for this cache. However if you want me to help you further you need to detail a little bit: Are you using any framework, javascript framework? Does the webpage create any workers becase they can act as cache, is it PWA etc...nodejs static app? Do you have a front CDN like cloudflare? – Jinxmcg Commented Mar 22, 2020 at 11:18
3 Answers
Reset to default 8 +50I think the browser caches the inline javascript only when the page is opened for subsequent calls in that session and does not keep it after you close or refresh the page.
However, this means that the browser gets the HTML (including JS) from its cache in your case. Therefore you could try sending some headers along with your page that force the browser not to use it's cached HTML copy and use the new html+js.
In order to test if it is a HTML cache or "inline JS" cache issue, make your html dynamically change and confirm that it is changing on refresh but the inline JS execution does not.
You can find more details regarding js cache here: https://v8.dev/blog/code-caching-for-devs
Using document.createElement('script')
to "refresh" your scripts is bad solution. Probably something else is wrong with your caching.
Have you tried
Cache-Control: "no-store, no-cache, must-revalidate, post-check=0, pre-check=0"
?
https://developer.mozilla/en-US/docs/Web/HTTP/Headers/Cache-Control
If you are using proxies check out proxy-revalidate.
When debugging you could try shift + F5 or holding shift while pressing the reload button to force a plete refresh in Google Chrome. (if you have changed your script)
Consider using the Cache-Control directive of max-age for your web page(s).
Normally, max-age might be set to a relatively long amount of time in seconds. This is done to improve performance by having the client frequently reuse cached files before they are refreshed.
Prior to releasing a change that you want the client to refresh immediately, drop the max-age value down to zero or a few seconds. Then, wait for the original max-age time duration to expire so that all active clients are updated with the new max-age value.
Once this wait period passes, push the file update(s) and revert to the original and longer max-age value.
This sequence will force the desired file change to be refreshed by the clients.