解决缓存问题_如何解决缓存难题

解决缓存问题

The web wouldn’t operate without caching. Between you and the server, there is a browser and any number of proxy servers which cache responses. Much of this is handled transparently by applications which dramatically reduce Internet traffic. However, it can also be the cause of bizarre web application quirkiness if you’re not very careful …

如果不进行缓存,网络将无法运行。 在您和服务器之间,有一个浏览器和许多可以缓存响应的代理服务器。 大部分应用程序可以透明地处理这些应用程序,从而大大减少了Internet流量。 但是,如果您不太谨慎,也可能导致Web应用程序古怪。

设置标题 (Set Your Headers)

Caching is controlled by the HTTP status code and the Last-Modified, Etag and Cache-Control headers returned by every request. For subsequent requests to the same URL, the browser/proxy will either:

缓存由HTTP状态代码以及每个请求返回的Last-ModifiedEtagCache-Control标头Cache-Control 。 对于后续对同一URL的请求,浏览器/代理将:

  1. retrieve the previous data from its own cache

    从自己的缓存中检索先前的数据
  2. ask the server to verify whether the data has changed, or

    要求服务器验证数据是否已更改,或者
  3. make a fresh request.

    提出新的要求。

The Cache-Control header primarily determines this action. It can set up to three comma-separated values:

Cache-Control标头主要确定此操作。 它最多可以设置三个逗号分隔的值:

no-store or no-cache no-store stops the browser and all proxy servers caching the returned data. Every request will therefore incur a trip back to the server.

no-storeno-cache no-store停止浏览器和所有代理服务器缓存返回的数据。 因此,每个请求都会导致返回服务器。

The alternative is no-cache. The browser/proxy will make a server request and pass back Last-Modified (date/time) and/or an Etag (response hash/checksum) in the header. These are present on subsequent requests and, if the response has not changed, the server returns a 304 Not Modified status, which instructs the browser/proxy to use its own cached data. Otherwise, the new data is passed back with a 200 OK status.

另一种选择是no-cache 。 浏览器/代理将发出服务器请求,并在标头中传回Last-Modified (日期/时间)和/或Etag (响应哈希/校验和)。 这些出现在后续请求中,如果响应未更改,则服务器返回304 Not Modified状态,该状态指示浏览器/代理使用其自己的缓存数据。 否则,新数据将以200 OK状态传回。

public or private Setting Cache-Control to public means the response is the same for everyone and the data can be cached in browser or proxy stores. It’s the default behavior, so it’s not necessary to set it.

publicprivateCache-Control设置为public意味着每个人的响应都是相同的,并且数据可以缓存在浏览器或代理存储中。 这是默认行为,因此无需进行设置。

private responses are intended for a single user. For example, the URL https://myapp.com/messages returns a set of messages unique to each logged-in user, even though both of them use the same URL. Therefore, the browser can cache the response, but proxy server caching is not permitted.

private回复仅针对单个用户。 例如,URL https://myapp.com/messages返回每个登录用户唯一的消息集,即使它们都使用相同的URL。 因此,浏览器可以缓存响应,但是不允许代理服务器缓存。

max-age This specifies the maximum time in seconds a response remains valid. For example, max-age=60 indicates the browser/proxy can cache the data for one minute before making a new request.

max-age此参数指定响应保持有效的最长时间(以秒为单位)。 例如, max-age=60表示浏览器/代理可以在发出新请求之前将数据缓存一分钟。

Your server, language and framework often control these settings, so you rarely need to tinker — but you can. Presume you wanted to cache an individual user’s JSON response to an Ajax request for 30 seconds. In PHP:

您的服务器,语言和框架通常会控制这些设置,因此您几乎不需要修改,但是可以。 假设您想将单个用户对Ajax请求的JSON响应缓存30秒。 在PHP中:

header('Cache-Control: private,max-age=30');
echo json_encode($data);

or a Node.js/Express router:

或Node.js / Express路由器:

res
    .set('Cache-Control', 'private,max-age=30')
    .json(data);

区分页面和Ajax数据URL (Differentiate Page and Ajax Data URLs)

Setting HTTP headers may not be enough, because browsers work in slightly different ways when you hit the back button.

设置HTTP标头可能还不够,因为单击后退按钮时浏览器的工作方式略有不同。

In Firefox and Safari, hitting back will attempt to show the previous page in its last known state — presuming the URL has been changed with an updated #hash, or by intercepting actions with history API events.

在Firefox和Safari中, 回击将尝试以上一个已知状态显示上一页-假定URL已使用更新的#hash进行了更改,或者通过拦截了具有历史记录API事件的操作进行了更改。

In Chrome and Edge, hitting back shows the previous page in its initial starting state — although your JavaScript will initialize and perhaps change the DOM if necessary.

在Chrome和Edge中, 回击会以其初始开始状态显示前一页-尽管您JavaScript会初始化,并且可能在必要时更改DOM。

In practice, it rarely matters which browser you’re using, but there are some weird edge cases. Presume your application presents a paginated table of records, which the user can search and click page navigation buttons. We’re good developers, so we’ll use progressive enhancement to ensure the system works in all browsers:

实际上,使用哪种浏览器都无关紧要,但是有一些奇怪的情况。 假设您的应用程序显示了一个分页的记录表,用户可以搜索并单击页面导航按钮。 我们是优秀的开发人员,因此我们将使用渐进式增强功能来确保系统在所有浏览器中均可正常运行:

  1. The user enters the page at http://myapp.com/list/

    用户在http://myapp.com/list/进入页面

  2. Submitting the form to change filters or navigate to a new page will change the URL and make a new request — for example, http://myapp.com/list/?search=bob&page=42. The system works in any browser with or without JavaScript.

    提交表单以更改过滤器或导航到新页面将更改URL并发出新请求-例如, http://myapp.com/list/?search=bob&page=42 //myapp.com/list/?search=bob&page= http://myapp.com/list/?search=bob&page=42 。 该系统可以在任何带有或不带有JavaScript的浏览器中使用。

  3. We introduce JavaScript enhancements so a full-page refresh isn’t required. The code intercepts the form submit and history back/next events so, while the URL still changes, the application performs an Ajax request in the background.

    我们引入了JavaScript增强功能,因此不需要整页刷新。 该代码拦截了表单提交和历史记录后退/后继事件,因此,尽管URL仍然更改,但应用程序在后台执行Ajax请求。
  4. The Ajax request calls the same URL such as http://myapp.com/list/?search=bob&page=42 — but sets the X-Requested-With HTTP header to XMLHttpRequest (done by jQuery and all good Ajax libraries). The server recognizes this header — so, instead of returning the full page HTML, it returns JSON-encoded record data. Our JavaScript uses this to update the DOM.

    Ajax请求调用相同的URL,例如http://myapp.com/list/?search=bob&page=42 ,但是将X-Requested-With HTTP标头设置为XMLHttpRequest (由jQuery和所有好的Ajax库完成)。 服务器可以识别此标头-因此,它不返回整页HTML,而是返回JSON编码的记录数据。 我们JavaScript使用它来更新DOM。

In summary, our server can either return HTML or JSON for the same URL, depending on the state of the request’s X-Requested-With header. Unfortunately, this can cause a problem with Chrome and Edge, because either HTML or JSON could be cached.

总而言之,我们的服务器可以针对相同的 URL返回HTML或JSON,具体取决于请求的X-Requested-With标头的状态。 不幸的是,这可能导致Chrome和Edge出现问题,因为可以缓存HTML或JSON。

Presume you randomly navigate around the record list and, at http://myapp.com/list/?search=bob&page=42, you click a link to another (non-list) page, followed by the browser back button to return. Chrome looks at its cache, sees JSON data for that URL and presents it to the user! Hitting refresh will fix the problem because a request will be made without the X-Requested-With header. What’s more bizarre is that Firefox works as expected and restores the actual page’s state.

假定您随机浏览记录列表,然后在http://myapp.com/list/?search=bob&page=42单击指向另一个(非列表)页面的链接,然后单击浏览器后退按钮以返回。 Chrome浏览器会查看其缓存,查看该URL的JSON数据并将其呈现给用户! 单击刷新将解决此问题,因为将在没有X-Requested-With标头的情况下发出请求。 更奇怪的是,Firefox能够按预期工作并恢复实际页面的状态。

The fix: ensure your page and data URLs are never the same. When navigating to http://myapp.com/list/?search=bob&page=42, the Ajax call should use a different URL: it can be as simple as http://myapp.com/list/?search=bob&page=42&ajax=1. This ensures Chrome can cache both the HTML and JSON requests separately, but JSON is never presented, because the Ajax URL never appears within the browser address bar.

解决方法:确保页面和数据URL永远不相同。 导航到http://myapp.com/list/?search=bob&page=42 ,Ajax调用应使用不同的URL:它可以像http://myapp.com/list/?search=bob&page=42&ajax=1 。 这样可以确保Chrome浏览器可以分别缓存HTML和JSON请求,但是永远不会显示JSON,因为Ajax URL永远不会出现在浏览器地址栏中。

(Note: please don’t use this example as justification for avoiding progressive enhancement! It can affect a JavaScript-dependent Single-Page Application — especially those providing links to external URLs.)

(注意:请不要使用此示例作为避免逐步增强的理由!它会影响与JavaScript相关的单页应用程序,尤其是那些提供指向外部URL链接的应用程序。)

Unfortunately, there’s a further complication …

不幸的是,还有进一步的复杂性……

当心自签名SSL证书 (Beware Self-signed SSL Certificates)

Ideally, your application is using the encrypted HTTPS protocol. However, there’s no need to purchase SSL certificates for all 57 members of your team, because you can use a fake, self-signed certificate and click proceed whenever a browser complains.

理想情况下,您的应用程序使用加密的HTTPS协议。 但是,无需为团队的所有57个成员购买SSL证书,因为您可以使用伪造的自签名证书, 在浏览器提出投诉时单击继续

Be aware that Chrome (and presumably most Blink-based browsers) refuses to cache page data when a fake certificate is encountered. It’s similar to setting Cache-Control to no-store on every request.

请注意,Chrome(可能是大多数基于Blink的浏览器)在遇到假证书时拒绝缓存页面数据。 这类似于将Cache-Control设置为对每个请求no-store

Your test sites will work exactly as expected, and you’ll never experience the same page/data URL issues described above. The cache is never used, and all requests return to the server. The same application on a live server with a real SSL certificate will cache data. Your users may report seeing strange JSON responses from Chrome — which you won’t be able to reproduce locally.

您的测试站点将完全按预期运行,并且您将永远不会遇到上述相同的页面/数据URL问题。 永远不会使用缓存,并且所有请求都将返回到服务器。 具有真实SSL证书的实时服务器上的同一应用程序缓存数据。 您的用户可能会报告看到来自Chrome的奇怪JSON响应- 您将无法在本地复制它们

These are the sorts of nightmare challenges that continue to plague web development! I hope you found this overview helpful. Feel free to share your own nightmares in the comments. We’re all in this together …

这些都是持续困扰Web开发的噩梦挑战! 希望本概述对您有所帮助。 随时在评论中分享自己的噩梦。 我们都在同一条船 …

翻译自: https://www.sitepoint.com/solve-caching-conundrums/

解决缓存问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值