我最近写了一篇博客文章,讲述了 图片有多难处理,最终形成了一份长长的清单,列出了在网站上放置图片时可以/应该考虑和实施的事项。
我认为,看到框架(我们利用这些广受喜爱的工具来帮助我们构建网站)在其内部提供了额外的工具来帮助解决这份清单,并承担起显示图片的艰巨任务(但非常适合计算机)是令人鼓舞的。
一些例子
我不确定我会给其中任何一个打出完美的颜色,就易用性而言。需要安装和配置一些东西,而且您可能只有在已经知道应该这样做的情况下才会使用它,并且您之前关于图片性能的知识可以帮助您完成整个过程。这不是这些框架的缺点;这些东西很复杂,目标用户是开发者,公平地说,他们对控制的想法有点着迷。
我必须在这方面感谢我的 BFF WordPress。您无需做任何事情,就可以 开箱即用地获得响应式图片。如果您需要利用过滤器来控制某些内容,您可以像在 WordPress 中处理任何其他内容一样做到这一点:通过钩子。如果您选择 Jetpack(我强烈 建议您这样做),您可以打开(非常棒且免费的) 网站加速功能,它会获取所有这些图片,对其进行优化,通过 CDN 托管,延迟加载,并在可能的情况下以 WebP 等格式提供服务(我假设将来会支持更多下一代格式)。Jetpack 是赞助商,所以这里需要完整披露,但我确实有意在使用它,因为这种体验使图片处理成为我根本不必考虑的事情。
框架辅助图片处理的另一个有趣方面是,其中一些源于 Google 的参与。Google 将其称为 “Aurora”
近两年来,我们与 Next.js、Nuxt 和 Angular 等一些最受欢迎的框架合作,致力于提高网页性能。
该项目执行各种操作,包括提供资金来帮助资助开源工具,以及直接帮助特定的计划。比如图片
Next.js 中的图片组件封装了图片加载的最佳实践,随后与 Nuxt 在此方面进行了合作。使用此组件已导致绘制时间和布局偏移有了显著改善(例如:nextjs.org/give 上的最大内容绘制减少了 57%,累积布局偏移减少了 100%)。
很酷,对吧?我认为是的?让我有点奇怪的是,当 Google 的团队加入框架贡献时,这感觉很有意义。他们肯定有意没有选择默默无闻的框架,因为他们希望自己的工作能影响到更多人。因此,已经取得成功的框架受益于 A 级团队的贡献。一种富者愈富的局面。我不确定这是否是一个大问题,但只是我思考的事情之一。
引言
我不了解 Gatsby 和 Eleventy 的图片组件,但我可以谈谈我对 NextJs 的看法。
首先,我认为 NextJs 在使图片对每个人都可用方面做得很好。他们真的突破了界限,几乎任何没有经验的新手开发人员都可以很快上手。
缺点
话虽如此,该组件也存在很多缺点。
傻瓜式设计对于入门者来说可能很棒,但它不会发展到此之外。
文章确实提到开发人员喜欢掌控一切,但这样做是有原因的……
巨大的 DOM 膨胀
每个图片都有 2 个包装器。这意味着,如果您页面上有 20 张图片,那么您已经在使用 60 个 DOM 节点。这真的效率不高,您可以轻松地只使用 1 个包装器来达到相同的效果。
样式选择:
!important
或更多 DOM 膨胀NextJs 图片组件不允许您访问其外部包装器,您只能控制
<img>
标签。为了给您的生活增添一些刺激,它还使用内联样式……
除非您想使用
!important
核选项结合易碎的 CSS 选择器,这在您更改页面上的某些内容时很容易出错,否则正确设置图片样式的唯一方法是在顶部添加额外的包装器。根据前面的示例,20 张图片现在从 60 个 DOM 节点增加到 80 个……
每个图片有 3 个包装器,而您可以只使用 1 个包装器来达到完全相同的效果。
哦,还有那些内联样式,您可以通过禁用其中的 77% 来在 95% 以上的浏览器上获得完全相同的效果……
内联样式 = CSP 问题
如果您想包含一个安全的内容安全策略 (CSP),那么您可以忘掉它了。内联样式与安全性直接冲突。
要么您通过使用
inline-unsafe
来降低安全要求,要么您应该寻求其他解决方案。大屏幕上的图片优化
默认情况下,图片优化基于视口。
这对于移动设备非常有效,您可以简单地使用 4K 图片作为源,它会根据用户的视口对其进行优化。这节省了大量的优化工作。
但是当应用于桌面时,此解决方案效果不佳。相同的 4K 图片仍然针对您的视口进行优化,而不是屏幕上的实际大小……
因此,如果您的视口为 2560px,但您想要一个 600px 的图片,则优化会为浏览器提供一个 2560px 的优化图片(来自 4k),浏览器会将其缩放到 600px 以适合您指定的宽度。
这是一个巨大的疏忽,传输的数据比应该的要多得多。在 4k 屏幕上,情况要糟糕得多。
客户端缓存机制
公平地说,NextJs 在 11.0 版本中为图片添加了
import
方法,这极大地改善了现状。新的
import
方法会自动在您的图片上添加一个带有immutable
的cache-control
标头,并在其名称上添加一个哈希值。有了此更改,用户无需在每次重新加载页面时都向您的服务器发送 ping 以查看图片是否仍然是最新的。但即使使用新方法,也存在缺陷
如果您的图片由用户提供会发生什么?
如果您的内容在 Markdown 中会发生什么?
好吧,运气不佳!您需要使用旧的图片方法,即将图片路径的字符串传递给组件。
旧方法不允许您选择缓存机制。您只能使用 60 秒的缓存,仅此而已。之后,每次重新加载都会向服务器发送 ping。当然,这只是一个 Etag 检查,但它仍然是一个网络请求,至少会增加 40 毫秒的延迟。
使用旧方法,您还可能遇到服务器动态重新优化图片的情况,这可能会导致长达 3 秒的延迟。
服务器缓存机制
这个也很有趣:优化的图片仅在服务器上保留 60 秒。
60 秒后,NextJs 会在下一个请求中重新优化您的图片。这可能需要 200 毫秒到 3000 毫秒。是的,3 秒,这不是错字。
无论您的图片是否已更改,NextJs 都会重新优化它。
图片优化使用 AWS 无服务器函数,该函数从您自己的 NextJs 账户执行。
虽然像这样分离图片非常安全,每个站点都是分开的,但如果您流量很大,则无服务器函数仍会每分钟执行一次。
将其乘以数十万个网站,就会造成巨大的资源浪费,他们肯定不会很快获得任何绿色环保奖……
如果您想更改 60 秒的缓存策略怎么办?
好吧,直到最近您还无法做到。此选项(我还没有时间测试)是在经过 8 个多月的无数投诉后才添加的。
结论
重要的是要提醒人们,这些框架为不熟悉的人做了很多好事。
但公平地说,它们做得还不够。我列出的问题只是我遇到的问题,还有其他一些问题……
这是一个非常复杂的问题,像 NextJs 这样的框架极大地帮助我们获得了简单的胜利。即使在我说了这么多之后,他们的解决方案仍然使整体情况变得更好。
我的观点更多的是,作为开发人员,我们需要对这些解决方案具有一定的控制权。这些框架的作用是为您提供最佳的默认值,或者它们认为是最佳的默认值,并提供大量处理程序来将其适应我们的情况。
这些信息很有用,感谢分享!