【问题标题】:Background images in css are not getting cachedcss中的背景图像没有被缓存
【发布时间】:2022-02-25 11:48:29
【问题描述】:

我有一些通过React.createElement 动态呈现内容的反应代码。因此,css 是通过对象应用的。该动态生成中的元素可以具有背景图像,指向公共 aws S3 存储桶。

似乎每次我的组件重新渲染时,都会再次从 S3 获取背景图像。这会延迟页面渲染。我在所有对象上设置了 Cache-Control 的 S3 元数据。这是背景图像加载的请求和响应标头 -

响应头 -

Accept-Ranges: bytes
Cache-Control: public, max-age=604800
Content-Length: 52532
Content-Type: application/octet-stream
Date: Sun, 06 Feb 2022 05:57:32 GMT
ETag: "f29655808a5f80627d9ea7f44058a5e3"
Last-Modified: Sun, 06 Feb 2022 05:55:10 GMT
Server: AmazonS3
x-amz-meta-filetype: IMAGE

请求标头 -

Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,hi;q=0.8
Cache-Control: no-cache
Connection: keep-alive
Host:  <bucket-name>s3.amazonaws.com
Pragma: no-cache
Referer: https://<my-domain>.com/
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Linux"
Sec-Fetch-Dest: image
Sec-Fetch-Mode: no-cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36

我可以在“网络”选项卡中看到图像被多次加载,并且它还显示每次都在进行数据传输。我在这里做错了什么?有人可以帮助找到根本原因。谢谢。

【问题讨论】:

  • 在有人说之前,我知道背景图片的尺寸太大了,但是由于它是用户定义的,所以用户可以上传一定尺寸的图片。此请求/响应测试数据。感谢理解。
  • 嗨@zookastos 你能确认我ETag 标头在不同的调用之间没有变化吗?您的网址是否会以某种方式从一个呼叫更改为另一个?你能考虑一个带有图像元素的预加载阶段吗?
  • 请给我一些时间来回复您此信息。同时,请您告诉我“预加载阶段”是什么意思。任何到 doc 的链接都会很好。谢谢
  • 花点时间看看这篇好文章,它可以帮助理解“预加载阶段”:Better Image Caching with CSS
  • 非常感谢这份文档

标签: css reactjs caching


【解决方案1】:

这可能是在开发工具的网络选项卡中选择了一个被遗忘的“禁用缓存”选项吗?因为似乎服务器以正确类型的缓存头响应。

【讨论】:

  • 天哪,就是这样。花了这么多小时和 50 声望才找到这个小复选框 :) 谢谢,很抱歉浪费了大家的时间。希望它在未来对其他人有所帮助。
【解决方案2】:

如果图片经过优化且不是很大,使用 base64 数据 url 是一个很好的解决方案。

const getBase64FromUrl = async (url) => {
  const data = await fetch(url);
  const blob = await data.blob();
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.readAsDataURL(blob); 
    reader.onloadend = () => {
      const base64data = reader.result;   
      resolve(base64data);
    }
  });
}

const image = getBase64FromUrl('the image url')

在创建你可以使用的元素时

background-image: `url(${image})`;

此外,我们很少直接从 S3 提供服务,您可能应该使用 cloudfront 作为代理来

  • 减少获取请求
  • 降低带宽费用
  • 在 cdn 缓存
  • 更好地控制缓存头
  • 隐藏您的 s3 真实网址

【讨论】:

    【解决方案3】:

    您看到网络请求的原因可能是因为您在请求中使用了Cache-Control: no-cache 标头。

    如下所示:

    no-cache response 指令表示响应可以是 存储在缓存中,但必须使用源验证响应 每次重用之前的服务器,即使缓存已与 源服务器。

    缓存控制:无缓存

    如果您希望缓存始终检查内容 在重用存储的内容时更新,no-cache 是指令 利用。它通过要求缓存重新验证每个请求来做到这一点 源服务器。

    请注意,no-cache 并不意味着“不缓存”。 no-cache 允许缓存 存储响应,但要求他们在重用之前重新验证它。 如果你想要的“不缓存”的感觉实际上是“不存储”, 那么 no-store 是要使用的指令。

    请看这里:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#response_directives

    当资产从验证请求返回 304 Not Modified 时,这是在我的网络选项卡上对缓存资产的完整请求的样子。 (来自 S3)这是在 background: url 上下文中。

    【讨论】:

    • 我没有通过 fetch 在我的请求中传递任何缓存控制标头。这是由 css 设置的背景图片 url - background: url('developer.mozilla.org/en-US/docs/Web/CSS/url()
    • 那是请求头......对服务器端没有任何意义
    • 如果我通过background: url 加载缓存的图像,我每次都会看到一个网络请求,它返回 304 Not Modified。例如,对于 1mb 的图像,有 390 个字节通过网络传输来检查状态。验证请求需要 155 毫秒。如果端点没有返回 Not Modified,则请求整个图像。
    • 另外,如果您添加像 ?2412314 这样的 url 参数,可能会使资产缓存无效,因此也可以检查一下。
    • 好的,请您显示您的请求、响应标头。感谢您对此的投入。
    猜你喜欢
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 2011-01-07
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 2020-07-14
    相关资源
    最近更新 更多