Alpha2k
Alpha2k

Reputation: 2241

How to refresh client INLINE javascript

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 come 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>

Upvotes: 6

Views: 2224

Answers (3)

JohnH
JohnH

Reputation: 2133

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.

Upvotes: 1

Enrico
Enrico

Reputation: 3454

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.org/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 complete refresh in Google Chrome. (if you have changed your script)

Upvotes: 1

Jinxmcg
Jinxmcg

Reputation: 1970

I 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

Upvotes: 8

Related Questions