Force Javascript File Update Without Disabling Cache

Asked

Viewed 23,311 times

23

In a large-scale web application I develop there is a disorder every time updates happen, because browsers, especially Google Chrome, do cache of Javascript files and, sometimes, incompatibilities occur between server and client code, leading to unforeseen situations and errors.

We have already considered converting our Javascript files so that their name loads the version number, thus making the browser consider them new files, but this showedif impracticable due to the large amount of files that exist and the confusion that this causes in our versioning (GIT).

Is there any standard or solution that forces the Javascript reload every time it is changed, without the user having to give a CTRL+F5 or clear the cache? Nor is it an option to disable cache of the pages.

  • Have you checked the META CACHE-CONTROL and EXPIRE? http://www.i18nguy.com/markup/metatags.html

  • I’ve seen the Cache-Control, but as far as I know only allows me to disable the cache, which I do not want. Already the Expires serves for search robots to withdraw them from their results when the date "expires".

  • 4

    Got it, about the version in the javascript file name you know you don’t necessarily have to be in the file name right? It might be something like seuarquivo.js?v=2

  • Yes, I had already seen this solution, but I gave it up because I read somewhere that the browsers were ignoring parameters of query string in archives .js. Can anyone there confirm that this solution is still viable and possible?

  • @Marcusvinicius may be that this give you an idea. We use query params to clean up the cache and has functioned smoothly so far.

  • Can generate a time() and put in the URL too.

  • Hello, So I checked I usually added a query string in the urls of the files as link : http://stackoverflow.com/questions/32414/how-can-i-force-clients-to-refresh-javascript-files http://stackoverflow.com/questions/15936050/force-browser-to-reload-all-cache-after-site-update http://blog.toddbauer.me/2013/01/30/forcing-browsers-to-reload-css-js-files/ This technique works because even if the file is cached if it is sent with a different querystring the browser interprets as if it were another file and performs the Reload.

Show 2 more comments

4 answers

18


Hello.

There is a technique called "Ghost Querystring" that solves this problem in most browsers.

In PHP it is done like this:

<link href="/file-css.css?<?php echo time(); ?>" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="/file-javascript.js?<?php echo time(); ?>"></script>

Rendered:

<link href="/file-css.css?1433981258" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="/file-javascript.js?1433981258"></script>

This generates a different URL in each "F5" and forces the browser to re-download the file.

This technique is used to avoid having to change the web server header settings.

Updating

The above solution can cause two problems:

1º) The increase of the internet traffic of the web server.
2º) The web application loads more slowly because it does not use the benefits of browser caching.

So to solve these two problems there are two solutions.

first solution:

Create a constant that would only be updated when CSS and JS files change version.

In ASP.NET:

I put a constant on the Web.config that indicates the version:

  <appSettings>
    <add key="Version" value="1254"/>
  </appSettings>

On the Site.Master I put:

<link href="/file-css.css?<%= ConfigurationManager.AppSettings["Version"] %>" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="/file-javascript.js?<%= ConfigurationManager.AppSettings["Version"] %>"></script>

In PHP:

It is recommended that the constant "VERSION" be created in a file of type "config.php". But I put it here only for demonstration:

<?php
define('VERSION', '1254');
?>
<link href="/file-css.css?<?php echo VERSION; ?>" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="/file-javascript.js?<?php echo VERSION; ?>"></script>

The two programming languages generate the same result in HTML:

<link href="/file-css.css?1254" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="/file-javascript.js?1254"></script>

second solution

Write the HTML itself by changing the numbering "1254" only when the CSS and JS files change version.

This last solution I consider the easiest.

References: Prevent Your CSS and Javascript Files From Being Cached

  • Interesting, but I want to keep the cache, I just want to update the file when it really changes. So I think I will use querystring with a constant value, which changes only when I change the contents of the file.

  • Control is in your hand. Hugs.

  • It’s been a while, but I’ll take it as you accept the answer for getting closer to the solution I found.

  • That’s not very healthy. @Marcusvinicius is right not to be satisfied. Downloading the same file, in the same version, each access is a bad practice.

  • The question is about ASP.NET and not PHP.

  • The response has been updated.

Show 1 more comment

3

As you are using ASP.NET, just use the resources of Bundling. It will manage this for you by creating a different URL only when there is a new version of Javascript, otherwise it will guide the browsers to recover the cache - http 306.

When you create an ASP.NET project with a template in Visual Studio, in the folder App_Start, will have a file called BundleConfig.cs.

In it you configure the groups of scripts or styles that will be published on the pages.

public class BundleConfig
    {
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/scripts/jquery").Include(
                "~/scripts/jquery-{version}.js"));

            bundles.Add(new ScriptBundle("~/scripts/meus-scripts").Include(
                "~/scripts/meuscript1.js",
                "~/scripts/meuscript2.js"));

            bundles.Add(new StyleBundle("~/content/site").Include(
                "~/content/site.css"));

#if DEBUG
            BundleTable.EnableOptimizations = false;
#else
            BundleTable.EnableOptimizations = true;
#endif

        }
    }

In their Views, consumes by passing the name of the groupings:

<html>
<head>
@Styles.Render("~/content/site")
</head>
<body>
    <!-- conteudo -->
    @Scripts.Render("~/scripts/jquery")
    @Scripts.Render("~/scripts/meus-scripts")
</body>
</html>

1

Marcus Vinicius, Taking the idea of Dadeke (Querystring Fantasma) and incrementing a little, I arrived at the following solution. Add a: <?php echo filemtime("includes/script.js"); ?>, this way when updating the script.js file, it will automatically change to 'querystring'.

Final result:

    <script src="script.js?"<?php echo filemtime("script.js"); ?>></script>
  • The question is about ASP.NET and not PHP.

0

This example needs a merge between: Database + Jquery + Json + ASP Classic( replace with your programming language) + HTML

Create a simple table in the database:

Tabela: atualize_me
Colunas: id( int, auto_increment ), status( bit, valor padrão: 1 )
Efetue um INSERT: insert into atualize_me(status) value(1)

put in the file( in my case file.js ) main that runs on all page of the site, the following information below:

$(document).ready(function(){
        // SE TIVER ALGUMA ATUALIZAÇÃO É SÓ IMPLEMENTAR 1 NO STATUS
        $.getJSON('json/json_atualize_me.asp',function(data){
                if( data[0].status == true ){
                        $.post('acao/json_atualize_me2.asp',{ status : 0 },function(data2){
                                window.location.reload(true);
                        });
                }else{  /* se quiser coloque algo aqui */ }
        });
});

Page content json_atualize_me.Asp:

<!--#include file="json_query.asp"--> ( veja mais informações sobre este arquivo )
<%
sql = "select status from "&bd_&".atualize_me;"
QueryToJSON(conn,sql).Flush
%>

Page content json_atualize_me2.Asp:

<!--#include file="../../bd/conn.asp"-->
<%
status = Replace(Trim(Request("status")),"'","")
sql = "update "&bd_&".atualize_me set status="&status&" where id=1;"
conn.execute(sql)
%>

In HTML include the call to the script:

<script type="text/javascript"  src="js/arquivo.js"></script>

Let’s say that the Site or System is already in Production/Online and are many customers accessing, just update the status field = 1 in the table update_me, ready the file itself will perform this request 1 time and if necessary Zera the browser cache. Note: Tested in Chrome and Firefox = ok

Browser other questions tagged

You are not signed in. Login or sign up in order to post.