How to force the browser to reload cached CSS/JS files?

后端 未结 30 4342
青春惊慌失措
青春惊慌失措 2020-11-21 05:49

I have noticed that some browsers (in particular, Firefox and Opera) are very zealous in using cached copies of .css and .js files, even be

相关标签:
30条回答
  • 2020-11-21 06:01

    Simply add this code, where you want to do hard reload (force browser to reload cached CSS/JS files ) Do this inside the .load so it does not refreshes like a loop

     $( window ).load(function() {
       location.reload(true);
    });
    
    0 讨论(0)
  • 2020-11-21 06:02

    Interesting post. Having read all the answers here combined with the fact that I have never had any problems with "bogus" query strings (which I am unsure why everyone is so reluctant to use this) I guess the solution (which removes the need for apache rewrite rules as in the accepted answer) is to compute a short HASH of the CSS file contents (instead of the file datetime) as a bogus querystring.

    This would result in the following:

    <link rel="stylesheet" href="/css/base.css?[hash-here]" type="text/css" />
    

    Of course the datetime solutions also get the job done in the case of editing a CSS file but I think it is about the css file content and not about the file datetime, so why get these mixed up?

    0 讨论(0)
  • 2020-11-21 06:02

    Just use server side code to add the date of the file... that way it WILL be cached and only reloaded when the file changes

    In ASP.NET

    <link rel="stylesheet" href="~/css/custom.css?d=@(System.Text.RegularExpressions.Regex.Replace(File.GetLastWriteTime(Server.MapPath("~/css/custom.css")).ToString(),"[^0-9]", ""))" />
    
    <script type="text/javascript" src="~/js/custom.js?d=@(System.Text.RegularExpressions.Regex.Replace(File.GetLastWriteTime(Server.MapPath("~/js/custom.js")).ToString(),"[^0-9]", ""))"></script>    
    

    This can be simplified to:

    <script src="<%= Page.ResolveClientUrlUnique("~/js/custom.js") %>" type="text/javascript"></script>
    

    By adding an extension method to your project to extend Page:

    public static class Extension_Methods
    {
        public static string ResolveClientUrlUnique(this System.Web.UI.Page oPg, string sRelPath)
        {
            string sFilePath = oPg.Server.MapPath(sRelPath);
            string sLastDate = System.IO.File.GetLastWriteTime(sFilePath).ToString();
            string sDateHashed = System.Text.RegularExpressions.Regex.Replace(sLastDate, "[^0-9]", "");
    
            return oPg.ResolveClientUrl(sRelPath) + "?d=" + sDateHashed;
        }
    }
    
    0 讨论(0)
  • 2020-11-21 06:04

    I've heard this called "auto versioning". The most common method is to include the static file's mtime somewhere in the URL, and strip it out using rewrite handlers or URL confs:

    See also:

    • Automatic asset versioning in Django
    • Automatically Version Your CSS and JavaScript Files
    0 讨论(0)
  • 2020-11-21 06:04

    Thanks at Kip for his perfect solution!

    I extended it to use it as an Zend_view_Helper. Because my client run his page on a virtual host I also extended it for that.

    Hope it helps someone else too.

    /**
     * Extend filepath with timestamp to force browser to
     * automatically refresh them if they are updated
     *
     * This is based on Kip's version, but now
     * also works on virtual hosts
     * @link http://stackoverflow.com/questions/118884/what-is-an-elegant-way-to-force-browsers-to-reload-cached-css-js-files
     *
     * Usage:
     * - extend your .htaccess file with
     * # Route for My_View_Helper_AutoRefreshRewriter
     * # which extends files with there timestamp so if these
     * # are updated a automatic refresh should occur
     * # RewriteRule ^(.*)\.[^.][\d]+\.(css|js)$ $1.$2 [L]
     * - then use it in your view script like
     * $this->headLink()->appendStylesheet( $this->autoRefreshRewriter($this->cssPath . 'default.css'));
     *
     */
    class My_View_Helper_AutoRefreshRewriter extends Zend_View_Helper_Abstract {
    
        public function autoRefreshRewriter($filePath) {
    
            if (strpos($filePath, '/') !== 0) {
    
                // path has no leading '/'
                return $filePath;
            } elseif (file_exists($_SERVER['DOCUMENT_ROOT'] . $filePath)) {
    
                // file exists under normal path
                // so build path based on this
                $mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $filePath);
                return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $filePath);
            } else {
    
                // fetch directory of index.php file (file from all others are included)
                // and get only the directory
                $indexFilePath = dirname(current(get_included_files()));
    
                // check if file exist relativ to index file
                if (file_exists($indexFilePath . $filePath)) {
    
                    // get timestamp based on this relativ path
                    $mtime = filemtime($indexFilePath . $filePath);
    
                    // write generated timestamp to path
                    // but use old path not the relativ one
                    return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $filePath);
                } else {
    
                    return $filePath;
                }
            }
        }
    
    }
    

    Cheers and thanks.

    0 讨论(0)
  • 2020-11-21 06:05

    Have not found the client sided DOM approach creating the script node (or css) element dynamically:

    <script>
        var node = document.createElement("script"); 
        node.type = "text/javascript";
        node.src = 'test.js?'+Math.floor(Math.random()*999999999);
        document.getElementsByTagName("head")[0].appendChild(node);
    </script>
    
    0 讨论(0)
提交回复
热议问题