NodeJS/express:缓存和 304 状态码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18811286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
NodeJS/express: Cache and 304 status code
提问by h345k34cr
When I reload a website made with express, I get a blank page with Safari (not with Chrome) because the NodeJS server sends me a 304 status code.
当我重新加载一个用 express 制作的网站时,我用 Safari(而不是 Chrome)得到一个空白页面,因为 NodeJS 服务器向我发送了一个 304 状态代码。
How to solve this?
如何解决这个问题?
Of course, this could also be just a problem of Safari, but actually it works on all other websites fine, so it has to be a problem on my NodeJS server, too.
当然,这也可能只是 Safari 的问题,但实际上它在所有其他网站上都可以正常工作,因此它也必须是我的 NodeJS 服务器上的问题。
To generate the pages, I'm using Jade with res.render.
为了生成页面,我将 Jade 与res.render.
Update:It seems like this problem occurs because Safari sends 'cache-control': 'max-age=0'on reload.
更新:这个问题似乎是因为 Safari'cache-control': 'max-age=0'在重新加载时发送。
Update 2:I now have a workaround, but is there a better solution? Workaround:
更新 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…
}
Update 3:So the complete code part is currently:
更新 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);
}
}
回答by blented
Easiest solution:
最简单的解决方案:
app.disable('etag');
Alternate solution here if you want more control:
如果你想要更多的控制,这里的替代解决方案:
回答by James P. Javery
As you said, Safari sends Cache-Control: max-age=0on reload. Express (or more specifically, Express's dependency, node-fresh) considers the cache stale when Cache-Control: no-cacheheaders are received, but it doesn't do the same for Cache-Control: max-age=0. From what I can tell, it probably should. But I'm not an expert on caching.
正如您所说,SafariCache-Control: max-age=0在重新加载时发送。Express(或者更具体地说,Express 的依赖项,node-fresh)在Cache-Control: no-cache收到标头时会考虑缓存陈旧,但它不会对Cache-Control: max-age=0. 据我所知,它可能应该。但我不是缓存方面的专家。
The fix is to change (what is currently) line 37 of node-fresh/index.jsfrom
解决方法是更改(当前是什么)node-fresh/index.jsfrom 的第 37 行
if (cc && cc.indexOf('no-cache') !== -1) return false;
to
到
if (cc && (cc.indexOf('no-cache') !== -1 ||
cc.indexOf('max-age=0') !== -1)) return false;
I forked node-fresh and express to include this fix in my project's package.jsonvia npm, you could do the same. Here are my forks, for example:
我分叉了 node-fresh 并表达了将此修复程序包含在我项目的package.jsonvia 中npm,您也可以这样做。这是我的叉子,例如:
https://github.com/stratusdata/node-freshhttps://github.com/stratusdata/express#safari-reload-fix
https://github.com/stratusdata/node-fresh https://github.com/stratusdata/express#safari-reload-fix
The safari-reload-fix branch is based on the 3.4.7 tag.
safari-reload-fix 分支基于 3.4.7 标签。
回答by user907567
I had the same problem in Safari and Chrome (the only ones I've tested) but I just did something that seems to work, at least I haven't been able to reproduce the problem since I added the solution. What I did was add a metatag to the header with a generated timstamp. Doesn't seem right but it's simple :)
我在 Safari 和 Chrome(我唯一测试过的)中遇到了同样的问题,但我只是做了一些似乎有效的事情,至少自从我添加解决方案以来我一直无法重现这个问题。我所做的是使用生成的时间戳向标头添加元标记。看起来不对,但很简单:)
<meta name="304workaround" content="2013-10-24 21:17:23">
UpdateP.S As far as I can tell, the problem disappears when I remove my node proxy (by proxy i mean both express.vhost and http-proxy module), which is weird...
更新PS 据我所知,当我删除我的节点代理时问题就消失了(通过代理我指的是 express.vhost 和 http-proxy 模块),这很奇怪......
回答by sbugert
Try using private browsing in Safari or deleting your entire cache/cookies.
尝试在 Safari 中使用隐私浏览或删除整个缓存/cookie。
I've had some similar issues using chrome when the browser thought it had the website in its cache but actually had not.
当浏览器认为它的缓存中有网站但实际上没有时,我在使用 chrome 时遇到了一些类似的问题。
The part of the http request that makes the server respond a 304 is the etag. Seems like Safari is sending the right etag without having the corresponding cache.
使服务器响应 304 的 http 请求部分是 etag。似乎 Safari 在没有相应缓存的情况下发送了正确的 etag。
回答by Codebeat
Old question, I know. Disabling the cache facility is not needed and not the best way to manage the problem. By disabling the cache facility the server needs to work harder and generates more traffic. Also the browser and device needs to work harder, especially on mobile devices this could be a problem.
老问题,我知道。不需要禁用缓存设施,也不是管理问题的最佳方法。通过禁用缓存设施,服务器需要更加努力地工作并产生更多流量。此外,浏览器和设备需要更加努力地工作,尤其是在移动设备上,这可能是一个问题。
The empty page can be easily solved by using Shift key+reload button at the browser.
在浏览器中使用 Shift 键+重新加载按钮可以轻松解决空页面。
The empty page can be a result of:
空页面可能是以下原因造成的:
- a bug in your code
- while testing you served an empty page (you can't remember) that is cached by the browser
- a bug in Safari (if so, please report it to Apple and don't try to fix it yourself)
- 你的代码中的一个错误
- 在测试时,您提供了一个由浏览器缓存的空页面(您不记得了)
- Safari 中的错误(如果是,请向 Apple 报告,不要尝试自行修复)
Try first the Shift keyboard key + reload button and see if the problem still exists and review your code.
首先尝试 Shift 键盘键 + 重新加载按钮,看看问题是否仍然存在并检查您的代码。

