【发布时间】:2017-08-07 23:48:17
【问题描述】:
我有一个用户图像控件,一个标识符 - 如果用户设置了图像,它应该显示它,如果没有,它会显示带有彩色背景(和一些其他 HTML)的他们的姓名首字母。
这些图片的数量很多,一次显示很多,而且同一用户可能会在一个页面上加载多次。图像可以包含 alpha 透明度,并以多种不同的背景颜色显示。图像可以是高 DPI,而后备(以及它们旁边显示的大多数其他图像)使用 SVG。
图像可以更改,但不会经常更改。通常它们可以被缓存几天或几周。
我认为有两种方法:
JavaScript
在此模型中,服务器返回我缓存在IndexedDB中的 JSON,并且 JSON 包含图像的数据 URI(如果已设置)。需要额外的 JS 来检查是否已经为同一用户发出请求并避免重复。HTML
<object>后备
为此,服务器返回实际的图像字节,如果未找到,则返回 404。然后,如果找不到图像,则<object>标记的内容呈现:
#identicon,
#identicon > div { display: inline-block; width: 50px; height: 50px; line-height: 50px; text-align: center; background-color: red; overflow: hidden; }
<object id="identicon" data="api/users/joebloggs/photo" type="image/png">
<div>JB</div>
<!-- some more HTML and SVG content, snipped here -->
</object>
<object id="identicon" data="http://placehold.it/50" type="image/png">
<div>PH</div>
<!-- some more HTML and SVG content, snipped here -->
</object>
JS 选项有很大的缺点,因为即使 JS 被高度优化 IndexedDB 意味着回调(或同步选项,如 LocalStorage,往往很慢)。这涉及相当多的 JS,这应该是一个相当简单的任务。它有一个很大的优势 - 它只要求每个用户的照片一次。
我喜欢 <object> 后备的简单性,它有一些小缺点(许多奇怪的规则适用于对象内的 HTML 的呈现方式),但一个主要问题是:如果找不到图像,它是圆形的每次都会再次跳闸服务器。很多用户没有图像。每次页面加载都会得到一长串 404 的用户图像,它应该已经知道没有。
- JS 是最好的方法,坚持下去 - 有什么方法可以减少 JS/开销?
- 将
<object>留给 404。 - 向
<object>添加一个事件,当它无法加载图像时触发一些 JS,但我不知道如何在不恢复到 (1) 的情况下阻止它再次尝试 - 更改服务器响应以在失败时返回用户图像。
这失去了后备的优雅,并意味着大量服务器生成的图像。
这就是 SO/gravatar 所做的,但对我们的高 DPI 屏幕来说意味着一些问题。 - 更改服务器响应以在失败时返回透明图像。
这意味着同一张图片会被缓存很多次,即使对于有照片的用户来说,也意味着对内容进行分层。它还会导致带有 Alpha 透明度的图像出现问题。 - 调整服务工作者以处理对用户图像的请求作为特殊情况,缓存 404 响应并在再次尝试时跳过网络往返。
- 滥用其他一些 HTTP 状态响应,
<object>仍将其视为无法找到图像并回退到内容,但由浏览器缓存。 - 其他方式?
所有这些都涉及妥协,但我也相当肯定我在这里重新发明了轮子 - 很可能有人(在所有已经存在的标识实现中)已经解决了这个问题。谁能指出我正确的方向或提出解决问题的最佳方法?
【问题讨论】:
-
我不确定我是否得到了所有东西,但你为什么不让浏览器自己处理它们的缓存呢?与其返回图片的胖 b64 数据,为什么不简单地从您的 API 发送 JSON 中的可缓存 URL 呢?只有这样,您才会使用接收到的 url 填充您的图像(无论是默认图像、来自您的用户的图像,还是只是一个让您知道必须生成它的标志)
-
@Kaiido 这是可能的——不过,我仍然需要从本地来源存储/检索该 URL。我仍然需要检查 Joe Bloggs 是否有照片,而 Jane Bloggs 没有来自
IndexedDB,然后等待回调,然后去获取图像。从 data-URI 切换到 URL 会减少初始请求的大小,但不会减少缓存的总大小,并且会在第一次看到每个用户时添加一个网络请求。 -
那么您可能可以将所有 URI 放入同步本地存储中。是的,它还会减少缓存:b64 编码将数据大小增加了约 30%。
-
@Kaiido 我不能 - 我已经尝试过了,页面在阅读时基本上挂起。
IndexedDB更快。 -
好吧,如果您将 b64 图像存储在 localStorage 中,是的,我相信浏览器在处理它时会遇到一些困难...检索简单的 JSON 数据
标签: javascript html css httpresponse html-object