NodeJS / express:缓存和304状态代码


91

重新加载使用express创建的网站时,使用Safari(而不是使用Chrome)会显示空白页,因为NodeJS服务器向我发送了304状态代码。

如何解决呢?

当然,这也可能只是Safari的问题,但实际上它可以在所有其他网站上正常工作,因此它也必须是我的NodeJS服务器上的问题。

为了生成页面,我将Jade与结合使用res.render

更新:似乎发生此问题,因为Safari'cache-control': 'max-age=0'在重新加载时发送。

更新2:我现在有一个解决方法,但是有更好的解决方案吗?解决方法:

app.get('/:language(' + content.languageSelector + ')/:page', function (req, res)
{
    // Disable caching for content files
    res.header("Cache-Control", "no-cache, no-store, must-revalidate");
    res.header("Pragma", "no-cache");
    res.header("Expires", 0);

    // rendering stuff here…
}

更新3: 因此,完整的代码部分当前为:

app.get('/:language(' + content.languageSelector + ')/:page', pageHandle);

function pageHandle (req, res)
{
    var language = req.params.language;
    var thisPage = content.getPage(req.params.page, language);

    if (thisPage)
    {
        // Disable caching for content files
        res.header("Cache-Control", "no-cache, no-store, must-revalidate");
        res.header("Pragma", "no-cache");
        res.header("Expires", 0);

        res.render(thisPage.file + '_' + language, {
            thisPage : thisPage,
            language: language,
            languages: content.languages,
            navigation: content.navigation,
            footerNavigation: content.footerNavigation,
            currentYear: new Date().getFullYear()
        });
    }
    else
    {
        error404Handling(req, res);
    }
}

1
304不是问题。这仅表示您的响应没有被修改,浏览器转向缓存以获取资源。您可以张贴发生异常的相关代码吗?
Akshat Jiwan Sharma

3
是的,实际上它没有被修改,但是Safari清空了CMD + R(重载)上的缓存,服务器只说它没有变化。
h345k34cr 2013年

空白页与304状态码有何关系?节点还将发送304到其他浏览器。
user568109 2013年

2
这是相关的,因为没有发送304正文,浏览器使用了它的缓存,但是由于没有缓存,您会得到一个空白页
h345k34cr 2013年

1
@AkshatJiwanSharma开发任何程序都是为了完全符合产品所有者的合同。产品所有者是拥有代码并付钱的人,而不是某个组织编写没人关心的文件。如果合同显示“ 200”,那么绝对不等于“ 200”的任何状态都是错误。当出现错误时,我必须重写代码,直到一切都完全符合预期为止。W3C对此没有发言权。
盖尔曼

Answers:


107

最简单的解决方案:

app.disable('etag');

如果您想要更多控制权,请在此处使用替代解决方案:

http://vlasenko.org/2011/10/12/expressconnect-static-set-last-modified-to-now-to-avoid-304-not-modified/


2
您能否解释“最简单的解决方案”或提供有关其影响的参考?
塞缪尔·门德斯

1
@SamuelMéndez它基本上禁用了缓存,etag上的Wiki有很多很好的信息en.wikipedia.org/wiki/HTTP_ETag
丰富了

为我工作:)
Naveen Kumar V

3

如您所说,Safari会Cache-Control: max-age=0重新加载。Express(或更确切地说,Express的依赖项,node-fresh)在Cache-Control: no-cache接收到标头时会考虑缓存过时,但对于则不这样做Cache-Control: max-age=0。据我所知,可能应该如此。但是我不是缓存专家。

解决方法是改变(目前是什么)线37node-fresh/index.js

if (cc && cc.indexOf('no-cache') !== -1) return false;  

if (cc && (cc.indexOf('no-cache') !== -1 ||
  cc.indexOf('max-age=0') !== -1)) return false;

我分叉了node-fresh,并表示将此修复包含在我的项目的package.jsonvia中npm,您可以执行相同的操作。例如,这是我的叉子:

https://github.com/stratusdata/node-fresh https://github.com/stratusdata/express#safari-reload-fix

safari-reload-fix分支基于3.4.7标签。


做得好!我看到Express 3.5.1通过节点新鲜0.2.2包含了您的修复程序。
Clafou 2014年

实际上,我错了,您的修复已还原,但实际上未达到0.2.2。仍然没有新鲜/快速修复。
Clafou 2014年

2

我在Safari和Chrome中遇到了相同的问题(我已经测试过的唯一问题),但是我所做的事情似乎可行,至少自从添加解决方案以来,我一直无法重现该问题。我所做的是使用生成的timstamp向标头添加元标记。看起来不正确,但很简单:)

<meta name="304workaround" content="2013-10-24 21:17:23">

更新 PS据我所知,当我删除节点代理(通过代理我指的是express.vhost和http-proxy模块)时,问题消失了,这很奇怪。


我也使用Apache代理,这可能是问题所在。我的解决方法是仅对具有http标头的内容网站禁用缓存。
h345k34cr

通过标头禁用缓存绝对是可行的方法。起初它对我不起作用,但现在对我有用。换句话说,我一定是在第一次的某个地方犯了一个错误:)
user907567

1

尝试在Safari中使用私人浏览或删除整个缓存/ cookie。

当浏览器认为网站具有缓存但实际上没有网站时,我在使用chrome时遇到了类似的问题。

使服务器响应304的http请求的一部分是etag。似乎Safari在发送正确的etag而没有相应的缓存。


当我尝试删除整个缓存时对我
有用

0

老问题,我知道。不需要禁用缓存功能,也不是解决问题的最佳方法。通过禁用缓存功能,服务器需要更努力地工作并产生更多的流量。浏览器和设备也需要更加努力地工作,尤其是在移动设备上,这可能是个问题。

使用浏览器上的Shift键和重新加载按钮可以轻松解决空白页。

空页可能是由于以下原因导致的:

  • 您代码中的错误
  • 在测试时,您提供了一个由浏览器缓存的空白页面(您不记得了)
  • Safari中的错误(如果是,请向Apple报告该错误,请勿尝试自行修复)

首先尝试使用Shift键盘键+重新加载按钮,查看问题是否仍然存在,然后查看代码。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.