Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何强制浏览器重新加载缓存的CSS和JavaScript文件_Javascript_Css_Caching_Auto Versioning - Fatal编程技术网

如何强制浏览器重新加载缓存的CSS和JavaScript文件

如何强制浏览器重新加载缓存的CSS和JavaScript文件,javascript,css,caching,auto-versioning,Javascript,Css,Caching,Auto Versioning,我注意到一些浏览器(特别是Firefox和)非常热衷于使用.css和.js文件的缓存副本,甚至在浏览器会话之间也是如此。当您更新其中一个文件时,这会导致出现问题,但用户的浏览器会继续使用缓存的副本 当文件发生更改时,强制用户浏览器重新加载文件的最优雅方式是什么 理想情况下,该解决方案不会强制浏览器在每次访问页面时重新加载文件 我发现你的建议很有用。事实证明,这有一个术语:自动版本控制 我在下面贴了一个新的答案,它是我原来的解决方案和约翰的建议的结合 SCdF提出的另一个想法是在文件中附加一个伪

我注意到一些浏览器(特别是Firefox和)非常热衷于使用.css.js文件的缓存副本,甚至在浏览器会话之间也是如此。当您更新其中一个文件时,这会导致出现问题,但用户的浏览器会继续使用缓存的副本

当文件发生更改时,强制用户浏览器重新加载文件的最优雅方式是什么

理想情况下,该解决方案不会强制浏览器在每次访问页面时重新加载文件


我发现你的建议很有用。事实证明,这有一个术语:自动版本控制

我在下面贴了一个新的答案,它是我原来的解决方案和约翰的建议的结合

SCdF提出的另一个想法是在文件中附加一个伪造的查询字符串。(一些Python代码自动将时间戳用作伪查询字符串,这是错误的。)


但是,对于浏览器是否会缓存带有查询字符串的文件,存在一些讨论。(请记住,我们希望浏览器缓存文件并在将来访问时使用它。我们只希望它在文件发生更改时再次获取文件。)

此解决方案是用PHP编写的,但它应该可以轻松地适应其他语言

原始的
.htaccess
regex可能会导致像
json-1.3.js
这样的文件出现问题。解决方案是,只有在末尾正好有10位数字时才重写。(因为10位数字涵盖了从2001年9月9日到2286年11月20日的所有时间戳。)

首先,我们在.htaccess中使用以下重写规则:

RewriteEngine on
RewriteRule ^(.*)\.[\d]{10}\.(css|js)$ $1.$2 [L]
现在,我们编写以下PHP函数:

/**
*给定一个文件,即/css/base.css,将其替换为包含
*文件的mtime,即/css/base.1221534296.css。
*
*@param$file要加载的文件。必须是绝对路径(即。
*从斜杠开始)。
*/
函数自动_版本($file)
{
如果(strpos($file,“/”)!==0 | |!file_存在($_服务器['DOCUMENT_ROOT'].$file))
返回$file;
$mtime=filemtime($\服务器['DOCUMENT\u ROOT'].$file);
返回preg_replace(“{\\.([^./]+)$}”、“$mtime.\$1”、$file);
}
现在,无论您将CSS包括在何处,都可以从以下内容进行更改:


为此:

<link rel="stylesheet" href="<?php echo auto_version('/css/base.css'); ?>" type="text/css" />

此解决方案是用PHP编写的,但它应该很容易适应其他语言

原始的
.htaccess
regex可能会导致像
json-1.3.js
这样的文件出现问题。解决方案是,只有在末尾正好有10位数字时才重写。(因为10位数字涵盖了从2001年9月9日到2286年11月20日的所有时间戳。)

首先,我们在.htaccess中使用以下重写规则:

RewriteEngine on
RewriteRule ^(.*)\.[\d]{10}\.(css|js)$ $1.$2 [L]
现在,我们编写以下PHP函数:

/**
*给定一个文件,即/css/base.css,将其替换为包含
*文件的mtime,即/css/base.1221534296.css。
*
*@param$file要加载的文件。必须是绝对路径(即。
*从斜杠开始)。
*/
函数自动_版本($file)
{
如果(strpos($file,“/”)!==0 | |!file_存在($_服务器['DOCUMENT_ROOT'].$file))
返回$file;
$mtime=filemtime($\服务器['DOCUMENT\u ROOT'].$file);
返回preg_replace(“{\\.([^./]+)$}”、“$mtime.\$1”、$file);
}
现在,无论您将CSS包括在何处,都可以从以下内容进行更改:


为此:

<link rel="stylesheet" href="<?php echo auto_version('/css/base.css'); ?>" type="text/css" />

您可以将
?foo=1234
放在CSS/JavaScript导入的末尾,将1234更改为您喜欢的任何内容。以堆栈溢出HTML源代码为例

这里的想法是,
参数在请求时被丢弃/忽略,您可以在推出新版本时更改该数字


注意:关于这究竟是如何影响缓存的,存在一些争论。我相信它的一般要点是,无论是否有参数,请求都应该是可计算的,因此上述解决方案应该是可行的


然而,这取决于web服务器决定是否要遵守规范的这一部分以及用户使用的浏览器,因为它可以直接要求一个新版本。

您可以在CSS/JavaScript导入的末尾添加
?foo=1234
,将1234更改为您喜欢的任何版本。以堆栈溢出HTML源代码为例

这里的想法是,
参数在请求时被丢弃/忽略,您可以在推出新版本时更改该数字


注意:关于这究竟是如何影响缓存的,存在一些争论。我相信它的一般要点是,无论是否有参数,请求都应该是可计算的,因此上述解决方案应该是可行的

然而,这取决于web服务器决定是否要遵守规范的这一部分以及用户使用的浏览器,因为它可以直接要求一个新版本。

我听说过这叫做“自动版本控制”。最常用的方法是将静态文件的修改时间包含在URL中的某个位置,并使用重写处理程序或URL配置将其删除:

另见:

我听说过这叫做“自动版本控制”。最常用的方法是将静态文件的修改时间包含在URL中的某个位置,并使用重写处理程序或URL配置将其删除:

另见:

如果将会话id添加为JavaScript/CSS文件的伪参数,则可以强制执行“会话范围缓存”:

<link rel="stylesheet" src="myStyles.css?ABCDEF12345sessionID" />
<script language="javascript" src="myCode.js?ABCDEF12345sessionID"></script>

如果需要版本范围的缓存,可以添加一些代码来打印文件日期或类似内容。如果您使用的是Java,则可以使用自定义标记以优雅的方式生成链接

<link rel="stylesheet" src="myStyles.css?20080922_1020" />
<script language="javascript" src="myCode.js?20080922_1120"></script>

如果将会话id添加为伪id,则可以强制执行“会话范围缓存”
http://mysite.com/css/[md5_hash_here]/style.css
script("/main.css")
<link rel="stylesheet" type="text/css"  href="/main.css?1221842734">
/styles/screen.css
/styles/screen.css?v=1234
/v/1234/styles/screen.css
body {
    background-image: url('images/happy.gif');
}
/v/1234/styles/images/happy.gif
<link rel="stylesheet" href="/css/base.css?[hash-here]" type="text/css" />
RewriteRule ^(.*)\.[^.][\d]+\.(css|js)$ $1.$2 [L]
/**
 * 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;
            }
        }
    }
}
<link href="mycss.css?v=<?= filemtime('mycss.css') ?>" rel="stylesheet">
example.css?randomNo = Math.random()
<script type="text/javascript" src="Scripts/exampleScript<%=Global.JsPostfix%>" />
<link rel="stylesheet" type="text/css" href="Css/exampleCss<%=Global.CssPostfix%>" />
protected void Application_Start(object sender, EventArgs e)
{
    ...
    string jsVersion = ConfigurationManager.AppSettings["JsVersion"];
    bool updateEveryAppStart = Convert.ToBoolean(ConfigurationManager.AppSettings["UpdateJsEveryAppStart"]);
    int buildNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Revision;
    JsPostfix = "";
#if !DEBUG
    JsPostfix += ".min";
#endif
    JsPostfix += ".js?" + jsVersion + "_" + buildNumber;
    if (updateEveryAppStart)
    {
        Random rand = new Random();
        JsPosfix += "_" + rand.Next();
    }
    ...
}
(function(){

    // Match this timestamp with the release of your code
    var lastVersioning = Date.UTC(2014, 11, 20, 2, 15, 10);
 
    var lastCacheDateTime = localStorage.getItem('lastCacheDatetime');

    if(lastCacheDateTime){
        if(lastVersioning > lastCacheDateTime){
            var reload = true;
        }
    }

    localStorage.setItem('lastCacheDatetime', Date.now());

    if(reload){
        location.reload(true);
    }

})();
<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>
exec('git rev-parse --verify HEAD 2> /dev/null', $gitLog);
echo '  <script src="/path/to/script.js"?v='.$gitLog[0].'></script>'.PHP_EOL;
<script src="{{ asset('/js/your.js?v='.filemtime('js/your.js')) }}"></script>
<link rel="stylesheet" href="{{asset('css/your.css?v='.filemtime('css/your.css'))}}">
<link rel="stylesheet" href="assets/css/your.css?v=1577772366">
$(window).load(function() {
    location.reload(true);
});
<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>
<script src="<%= Page.ResolveClientUrlUnique("~/js/custom.js") %>" type="text/javascript"></script>
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;
    }
}
<script src="https://jessietessie.github.io/google-translate-token-generator/google_translate_token_generator.js" integrity="sha384-muTMBCWlaLhgTXLmflAEQVaaGwxYe1DYIf2fGdRkaAQeb4Usma/kqRWFWErr2BSi" crossorigin="anonymous"></script>
// Pure JavaScript unique query parameter generation
//
//=== myfile.js

function hello() { console.log('hello') };

//=== end of file

<script type="text/javascript">
    document.write('<script type="text/javascript" src="myfile.js?q=' + Date.now() + '">
    // document.write is considered bad practice!
    // We can't use hello() yet
</script>')

<script type="text/javascript">
    hello();
</script>