以下是 Mat Marquis 的客座文章。 Mat 向我们发布了一则关于响应式图像的重要 PSA。
我不想埋没重点:如果您使用的是 2.3.1 之前的 Picturefill 版本,请立即更新——更新您的 /lib
文件,在您的项目中提交问题,或运行快速 npm update picturefill
命令,让您的心安理得。 Picturefill 2 的任何版本都没有重大更改,因此您在更新时不应遇到任何问题。
这里没有发生火灾。 Picturefill 不可能存在任何严重的安全性问题;由于 Picturefill 的错误,没有人会对您的兆赫进行网络攻击,或者电视上是如何进行黑客攻击的。此问题对您的项目可能意味着图像损坏,而对网络标准而言——嗯,这可能是一个更大的问题。
问题
使用旧版本的 Picturefill,您可能会在 WebKit nightly 和 Microsoft Edge 预览版中遇到图像损坏问题。 这就是我们在响应式图像行业所说的“遇到严重问题”。
响应式图像规范的一小部分但很重要的一部分是向 img
添加 currentSrc
属性,使我们能够通过 JavaScript 获取当前显示的源。 使用过去多年的普通 img
,我们始终可以假设 src
属性的值是正在显示的源——毕竟它是图像源的唯一选项。 现在,我们有了大量新的选项以更负责任和上下文相关的方式提供图像,因此 src
属性可能不包含当前显示给用户的源——因此有了 currentSrc
。
Picturefill 通过将当前源写入自定义 currentSrc
属性来模拟此功能,并且没有原生响应式图像支持的浏览器不会介意这一点。 但是,浏览器中的原生 currentSrc
实现是只读的。 问题的关键在于 Picturefill 使用 JavaScript use strict
声明,这意味着 Picturefill 对潜在错误非常敏感。 当我们试图创建一个在任何地方都能正常工作的 100% 符合规范的 polyfill 时,我们最不希望看到的是静默错误。 当 Picturefill 尝试做一些浏览器不希望它做的事情时,我们不希望浏览器为我们提供例外。 我们希望立即了解该问题——并解决它。 在这种情况下,浏览器反对 Picturefill 尝试写入只读属性。
Picturefill 依靠对 picture
元素支持的测试来决定它是否应该完全运行——这是其最早版本中的一个遗留问题。 当 WebKit 和 Edge 预览版在没有 picture
的情况下推出对 srcset
和 sizes
的支持时,Picturefill 对 picture
元素的测试失败,因此它尝试模拟原生支持的功能。 这包括尝试写入 currentSrc
,这导致了 strict mode
异常。 异常会导致 JavaScript 停止运行,因此 Picturefill 停止了——结果,没有显示使用 srcset
的图像。
我们的错误——我的错误,老实说——是被对原生实现的关注所宠坏。 很长一段时间以来,我们在响应式图像支持方面拥有清晰的分界:浏览器要么仅支持基本的 srcset
(仅 1x
、2x
“设备像素比”语法),要么支持 picture
、完整的 srcset
、sizes
以及所有内容。 由于浏览器支持存在如此可预测的差异,因此这始终运行良好——并且当事情运行良好时,您不会过多考虑它们。 当铰链不发出吱吱声时,没有人会注意到。
更大的问题
这很糟糕,但从代码角度来看,很容易修复。 它是软件;这些事情会发生。 这并不意味着此类问题类似于“可以”,但错误确实会发生。 更大的问题是问题的潜在范围。
Picturefill 出现在 picture
、srcset
或 sizes
成为浏览器开发人员眼中共同的闪光之前,我们将其用作原型来告知 响应式图像规范,从最初的草稿开始。 在成为所有这些语法的第一个真正的polyfill之一后,Picturefill 广受欢迎——大量网站都在使用它。 这使得它成为一个严重的问题,而不仅仅是缺少图像:如果此问题应该进入稳定浏览器而不是仅限于 nightly 和预览版本,它将影响大量网站。
因此,Microsoft Edge 暂时删除了 currentSrc
支持;第一个稳定版本将提供 srcset
和 sizes
,但没有 currentSrc
。 WebKit 也可能这样做。 但是,如果问题仍然存在,我们无法知道这个非常必要的特性何时会被重新启用——如果会被启用的话。 供应商无法冒数百——数千——个网站在其浏览器中崩溃的风险。 在我们更新 Picturefill 之前,我们无法在 WebKit 或 Edge 中使用 currentSrc
——如果它们完全删除它,其他浏览器也可能会这样做。
说真的,请更新 Picturefill
响应式图像的出现归功于我们所有人。 不是 RICG,不是任何一个人,也不是任何“核心”网络标准决策者群体——这些是我们设计师和开发人员争取的特性,付费的,并使其成为现实。
但是,新的网络标准的最终目标很漫长。 现在,我们已经开始获得我们长期以来一直追求的响应式图像,我们有责任让所有这些都朝着正确的方向发展——在这种情况下,这意味着我们需要进行一些维护。 这可能像键入 npm update picturefill
那样简单,也可能像复制粘贴文件内容那样复杂——但在任何一种情况下,这都需要几分钟的工作。 整个响应式图像团队都在这里帮助解决任何可能出现的问题,我们也会密切关注与更新到 2.3.1 相关的问题,因为我们所有的工作都依赖于 Picturefill 不妨碍原生实现。 如果您在更新时确实遇到任何问题——尽管我不认为您会遇到——请不要犹豫直接给我发送电子邮件。 Picturefill 团队——以及整个 RICG,如果需要的话——将帮助您解决问题。
作者注:感谢 Alex Jegtnes 和 Sarah Forst 的编辑。
我从未想过会在 css-tricks 上看到指向 xkcd 的链接。 也许我之前没有认真寻找过。 文章也很棒。
大多数项目似乎仍在使用 Picturefill 1.x,因为如果禁用 JS,2.x 仍然无法显示任何图像。 这会影响 1.x 吗?
在 1.X 中不是问题,因为 1.X 不会模拟原生功能。
我很好奇:我们看到了更多 Picturefill 2.X 的活动,但只是轶事——没有我可以轻松引用的东西。 您是否查看过/分析过各个版本的用量数据?
Picturefill 的替代方案是 respimage。
请在此处查看 – https://github.com/aFarkas/respimage
事实上,afarkas 是 Picturefill 团队的成员! 我们在这两个项目之间分享了许多想法和代码,并且他负责 Picturefill 3 Alpha 的开发。
喜欢引言 :-)
在那之后,您有点为生产代码中不使用
use strict
辩护了……我过去确实听过有人说过这句话,我本人也可能被说服。 但是,对于 Picturefill 而言,我们宁愿在足够早的时候看到一个大胆的错误,以便在它影响到稳定浏览器之前将其修复(例如这个案例),也不愿冒将来某个地方出现静默神秘错误的风险。