Angular JS 1 - 缓存问题

16 浏览
0 Comments

Angular JS 1 - 缓存问题

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

当文件发生变化时,如何优雅地强制用户的浏览器重新加载文件?

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


我发现John Millikin和da5id的建议非常有用。原来有一个术语可以描述这个问题:自动版本控制。

我在下面发布了一个新的答案,结合了我的原始解决方案和John的建议。

另一个由SCdF提出的想法是向文件添加一个虚假的查询字符串。(一些Python代码可以自动使用时间戳作为虚假的查询字符串,由pi提交。)

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

0
0 Comments

AngularJS 1 - 缓存问题的出现原因和解决方法

在开发网站过程中,缓存是有好处的。根据你是在开发网站时为自己解决问题,还是在生产环境中控制缓存,有一些不同的技巧。

对于普通访问者来说,他们不会像你在开发网站时那样频繁访问网站。除非你是Google或hi5 Networks,否则他们每个月可能只会访问几次。因此,他们在缓存中可能没有你的文件,这可能已经足够了。

如果你想强制浏览器加载新的文件版本,你可以在请求中添加一个查询字符串,并在进行重大更改时增加版本号:

<script src="/myJavascript.js?version=4"></script>

这将确保每个人都获得新的文件。这种方法有效是因为浏览器查看文件的URL来确定是否有缓存的副本。如果你的服务器没有设置处理查询字符串的功能,它将被忽略,但对于浏览器来说,文件名看起来像一个新文件。

另一方面,如果你正在开发一个网站,你不想每次保存开发版本的更改时都改变版本号,这将非常繁琐。

因此,在开发网站时,一个好的技巧是自动生成查询字符串参数:

<!-- Development version: -->
<script>document.write('<script src="/myJavascript.js?dev=' + Math.floor(Math.random() * 100) + '"\><\/script>');</script>

在请求中添加查询字符串是对资源进行版本控制的一种好方法,但对于一个简单的网站来说,这可能是不必要的。并且要记住,缓存是件好事。

值得注意的是,浏览器对于保留缓存文件并不一定吝啬。浏览器对此有一些策略,通常遵循HTTP规范中的规定。当浏览器向服务器发送请求时,响应的一部分是一个Expires头,它告诉浏览器应该将文件保留在缓存中的时间。下次浏览器遇到同一文件的请求时,它会看到自己的缓存中有一个副本,并根据Expires日期来决定是否使用它。

所以,信不信由你,实际上是你的服务器使得浏览器缓存如此持久。你可以调整服务器设置并更改Expires头,但我上面写的小技巧可能是你更简单的方法。由于缓存是好事,你通常希望将该日期设置得很远(“远期过期头”),并使用上述描述的技巧来强制更改。

如果你对HTTP或这些请求是如何进行的更多信息感兴趣,可以阅读Steve Souders的《高性能网站》一书。这是一个非常好的介绍性书籍。

使用Javascript生成查询字符串的快速技巧在开发过程中非常有效。我在PHP中也使用了同样的方法。

这是实现原始发布者所需结果的最简单方法。如果你想在加载页面时强制重新加载.css或.js文件,使用mod_rewrite方法效果很好。这种方法仍然允许缓存,直到你真正改变文件并且需要强制重新加载内容。

如果你希望在不对每个页面进行编码的情况下解决问题,我有大量的jQuery。如果你能帮我解决这个问题,那就太好了。

我已经尝试了这个解决方案在不同的浏览器上:在JS文件URL的末尾添加一个版本号。有趣的是,Opera 25.0、Firefox 34.0和Chrome 39.0.2171.65不会将文件保留在缓存中,只要末尾有版本号,即使数字没有改变。IE 11.0和Safari 5.1.7的工作方式与预期相同。

如果我将这个查询字符串脚本写在一个单独的JS文件中,而不是添加到站点的所有页面中,它会起作用吗?如果可以,怎么做?

如果你觉得运气不好,你可以考虑使用Date.now()代替随机值。

当我使用以下代码时,这种方法似乎对我的CSS不起作用:<link href='myCss.css?dev=14141'...>

这里的指针非常有帮助。我有一个单页面应用程序,我只需要在发布时更新一个index.html文件。但手动修改仍然很可怕。我编写了一些代码和一个应用程序来实现它-我写了一个回答这个问题的答案(可能在最后,因为它是新的-不是因为它不好),它描述了它的工作原理并包含了代码。希望它能帮助到其他在类似情况下开发的人。

这是列出的最佳和最可靠的解决方案,因为它避免了服务器操作、不可靠的HTTP头缓存,并保留了浏览器自动进行的本地缓存。如果你开始劫持服务器并重写URL,就会在用户之间创建一个潜在的混乱调用,而这些调用是无法管理的。这个简单的查询字符串技巧自上世纪90年代以来一直存在,所以大多数年轻人不知道它的存在。浏览器和服务器本身使用HTTP头来缓存图像和脚本。这就是为什么如果你了解缓存,就不需要使用AngularJS路由和其他技巧的原因。

这不是一个可行的解决方案。很多浏览器会拒绝缓存带有查询字符串的任何内容。这就是为什么Google、GTMetrix和类似的工具会发出警告,如果你在静态内容的引用中有查询字符串。虽然它在开发过程中确实是一个不错的解决方案,但绝对不是生产环境的解决方案。此外,缓存是由浏览器控制的,而不是服务器。服务器只是建议何时刷新;浏览器不一定要听从服务器(通常不会)。移动设备就是一个很好的例子。

document.write的解决方案效果太好了,现在我无法在Chrome中设置断点,因为URL不断变化,从而不断刷新并且丢失了我的断点!

我更喜欢这个解决方案,因为它不需要服务器端修复。我现在只使用客户端代码(即,.php、.asp等)。我只开发纯客户端,只有ajax调用从服务器获取数据,以及js代码和css样式。而且Chrome似乎对css像银行对待金条一样。属于我!

简单而有效,我喜欢!

0
0 Comments

Angular JS 1 - 缓存问题

在这篇文章中,我们将讨论一个关于Angular JS 1中的缓存问题,以及解决这个问题的方法。

Google的mod_pagespeed插件可以为你自动创建版本号。它在Web服务器发送HTML时解析HTML(适用于PHP,Ruby on Rails,Python,静态HTML等任何内容),并重写CSS、JavaScript和图像文件的链接,使其包含一个ID代码。它以修改后的URL提供文件,并设置了非常长的缓存控制时间。当文件发生变化时,它会自动更改URL,以便浏览器必须重新获取它们。它基本上是一个可以自动工作的工具,而无需对你的代码进行任何更改。它甚至可以在输出时对你的代码进行压缩。

然而,由于它仍处于测试阶段,因此它能够用于企业服务吗?

这是错误的(自动修改源代码),因为这显然是一个浏览器问题。给我们(开发者)一个真正的刷新:<ctrl>+F5。

mod_pagespeed在功能上等同于为你的HTML/CSS/JS进行完全自动化的构建/编译步骤。我认为很难找到任何认为构建系统本质上是错误的严肃开发者,或者认为完全自动化是错误的。类似于清理构建的比喻是清除mod_pagespeed的缓存。

mod_pagespeed不需要对你的源代码进行任何操作来进行缓存管理,只是提到它可以帮助进行代码压缩等操作。至于它是否“错误”,这完全是主观的。它可能对你来说是错误的,但这并不意味着它本质上是“坏”的。

然而,这只是将问题从客户端转移到服务器端,因为如果聚合样式表被更新,但pagespeed缓存没有被更新,用户将得到旧的样式表。

最新发布的版本非常棒!所有的CSS和JS链接都被聚合成一行,并附加了一个版本号。我按照这些说明在我的Debian系统上进行了配置。

它也可以在Nginx上使用,但你需要从源代码进行构建。

并不只有开发者使用网站。对于普通用户来说,ctrl+F5并不是一个好的解决方案,我们不希望他们看到旧的版本。

注意:mod_pagespeed现在已经存档。

以上就是关于Angular JS 1中缓存问题的原因和解决方法的整理。

0
0 Comments

Angular JS 1 - 缓存问题的出现原因及解决方法

在使用Angular JS 1时,可能会遇到一个缓存问题。具体表现为,当在CSS或JS文件中进行更改时,浏览器不会重新加载这些文件,而是继续使用缓存的副本,导致用户无法看到最新的CSS样式。

这个问题的出现原因是浏览器对静态文件进行缓存,而不会重新加载。解决方法是通过改变文件的链接来让浏览器认为这是一个新的URL,从而重新加载文件。下面是解决该问题的具体步骤:

1. 首先,在.htaccess文件中添加以下重写规则:

RewriteEngine on
RewriteRule ^(.*)\.[\d]{10}\.(css|js)$ $1.$2 [L]

这个规则的作用是,只有当链接的末尾恰好有10个数字时,才进行重写。这样可以避免对类似"json-1.3.js"这样的文件进行重写。

2. 接下来,编写一个名为"auto_version"的PHP函数。该函数的作用是将文件名替换为带有文件的修改时间的字符串。具体代码如下:

function auto_version($file) {
  if($file[0] !== '/') {
    $file = rtrim(str_replace(DIRECTORY_SEPARATOR, '/', dirname($_SERVER['PHP_SELF'])), '/') . '/' . $file;
  }
  if (!file_exists($_SERVER['DOCUMENT_ROOT'] . $file))
    return $file;
  $mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $file);
  return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $file);
}

3. 在需要引入CSS文件的地方,将原来的链接修改为调用"auto_version"函数来获取新的链接。例如,将原来的代码:


改为:


通过这样的修改,您无需再修改链接标签,用户将始终看到最新的CSS样式。浏览器可以缓存CSS文件,但当您对CSS进行任何更改时,浏览器将将其视为新的URL,从而不使用缓存的副本。

这种方法也适用于图片、网站图标和JavaScript等静态文件。基本上,适用于任何不是动态生成的文件。

这个解决方案非常巧妙,使用URL重写可以实现更多功能,而不仅仅是优化URL。同时,这种方法避免了使用查询字符串的问题,因为某些公共代理服务器不会缓存带有查询字符串的文件。

总之,通过使用上述的步骤,您可以解决Angular JS 1中的缓存问题,确保用户始终看到最新的CSS样式。

0