Firefox 158:JPEG XL怎么部署

黎 浩然/ 14 10 月, 2026/ 研究生/POSTGRADUATE, 计算机/COMPUTER/ 0 comments

Firefox 158 默认启用 JPEG XL,让网站多了一种可直接发送的图片格式。值得试,但不必马上把全站图片换掉:先准备兼容回退,用同等画质的样本比较文件大小,再核对缓存和解码,才能知道访客有没有得到实际收益。

文章目录
  1. 这次改变发生在哪里
  2. 先分清三种“没有损失”
  3. 先用独立地址把回退写清楚
  4. 同一个地址协商格式,缓存也要参与
  5. 把“变小了”换算成整站收益
  6. 下载省下的时间,不一定等于更早显示
  7. 一个适合博客的小范围试验
  8. 参考资料

这次改变发生在哪里

Google News 中的 Linuxiac 报道发表于10月12日;Mozilla 官方将 Firefox 158 的 Release 渠道日期列为2026年10月13日。两者不是同一个时间口径:提前报道文件可用,与正式渠道发布日期应分开记录。本文依据已经公开的官方版本说明和开发者文档,不将媒体日期写成官方发布日期。

MDN 的 Firefox 158 说明确认 JPEG XL 默认开启,图片请求的默认 Accept 头也加入 image/jxl。对站长而言,前者关系到解码,后者关系到服务器是否能识别客户端能力。这两件事合在一起,才构成实际部署的起点。

这里关注的是照片、截图和文章配图的发送路径,而不是让某种扩展名替代全部图片。以前的版本、嵌入式浏览器及仍未升级的设备,不能仅凭“Firefox支持了”就被视为已经兼容。对本站这样的图文博客,第一步应是小范围比较,而非先改收款二维码或历史配图。

先分清三种“没有损失”

JPEG XL 同时支持有损、无损,以及对已有 JPEG 的无损转码。原始无损图像编码、有损图像的视觉质量、已有 JPEG 的无损重构,是不同目标。项目的参考实现 libjxl提供编码与解码工具;是否保留已有 JPEG 的可重构信息,要看所选模式与参数,不能由文件名推断。

比如,把一张已经有损的 JPEG 做可逆转码,并不会恢复相机原始数据中早已丢失的细节。它保留的是已有内容或编码信息。反过来,拿较大的旧文件与一张重新有损编码、细节减少的新图比较,也不能证明格式本身就更优秀。

比较前先写下用途:照片是否允许少量视觉差异;截图上的小字是否仍清楚;透明边缘是否正确;颜色配置和目标设备是否一致。正文流程图尤其要看细线、数字和字符边缘,而不是只缩小到缩略图后觉得“差不多”。同一个编码器质量数值也不能跨格式当成相同画质。

可靠的比较应固定显示尺寸和图像内容,保留原始文件,记录编码器版本、参数与输出字节数,再检查实际画面。没有这些条件,漂亮的压缩百分比仍不足以决定迁移。这篇文章给出的数值只用于计算方法,不借用厂商的通用比例替代你的素材实测。

先用独立地址把回退写清楚

小站最容易核对的一条路径,是让同一内容拥有 .jxl 与已有兼容格式的独立地址。HTML 的 picture 可以通过 source 的 type 选择格式。MDN picture 文档解释了这套选择规则。

同一张内容图片
↓
浏览器支持 image/jxl?
支持 → 选择 .jxl source
不支持 → 使用 .jpg img
请求所选地址 → 解码 → 显示
原创选源流程:格式支持决定选择;所选地址出错,不等于会自动尝试另一种格式。
<picture>
  <source srcset="/images/diagram-1200.jxl" type="image/jxl">
  <img src="/images/diagram-1200.jpg"
       width="1200" height="800"
       alt="图片发送架构"
       style="max-width:100%;height:auto">
</picture>

这些路径是部署示意,使用前必须替换成已生成且可访问的真实文件。img 提供内容说明和尺寸,source 提供格式候选;图像宽高应与素材比例一致。alt 描述图片所传达的信息,不用来堆砌格式名称或SEO关键词。

这个回退回答的是“浏览器不支持候选格式时选什么”。如果浏览器已选择 JXL,但该地址返回404、内容类型错误或文件损坏,不能假定它会自动改试 JPEG。上线前要分别打开两份文件、检查响应内容,并在不支持该候选格式的目标环境中确认选择结果。

首次试验可放在非关键图片上,保留原地址,比较开发者工具中的实际选源与页面显示。不要把首页关键图、支持二维码、全部旧文都当成一次试验。三张支持图片的扫描可读性和原收款目标,优先于任何文件体积节省。

同一个地址协商格式,缓存也要参与

另一条路径是同一图片地址根据 Accept 返回不同编码。这样 HTML 可以较简单,但服务器与 CDN 必须知道:相同 URL 可能对应不同响应体。Vary 响应头用于表明哪些请求头影响响应选择;用 Accept 协商时,通常需要 Vary: Accept,同时核对缓存服务自身的配置。

只在源站加头还不够证明链路正确。CDN、代理和应用缓存可能有各自的变体规则;把支持 JXL 的请求先缓存,再向不支持的客户端发送同一份响应,就是要排查的典型问题。Content-Type 也必须对应实际字节,不能只给 JPEG 换个后缀。

显式格式地址与内容协商的主要取舍如下。它是部署分析,不是某家 CDN 的功能承诺。

路径 方便之处 主要检查点
不同格式独立地址 HTML里能看到候选 每个候选都要有有效文件
同址内容协商 一个公开地址 响应变体与缓存键必须一致

无论哪条路径,测试时都要交换访问顺序:支持客户端先访问一次,不支持客户端再访问;然后清理测试缓存,反过来再做。只测一个客户端的一次成功加载,无法发现变体互串。还要记录缓存命中与重新下载,避免把缓存热身误认成格式加速。

把“变小了”换算成整站收益

假设一张原格式图片为300 kB,JXL候选为210 kB,80%的相关发送能使用新格式,其余仍用原格式。这里 kB 取1000字节。成功使用新格式的那部分节省30%,但加权平均大小为0.8×210+0.2×300=228 kB,整体节省24%。

原格式:300 kB
JXL候选:210 kB
加权发送:228 kB
原创假设模型:十进制kB,假设支持占比80%。不是图片编码实测,也不是普遍压缩率。

再假设有10万次图片请求,其中60%由客户端有效缓存直接提供,不重新传输响应体。剩下4万次传输,按每次节省72 kB,得到约2.88 GB 的响应体流量差额。这些假设不代表本站访问量、浏览器分布或收入;需要换成真实口径才有经营意义。

缓存所在的位置不能含糊。CDN命中可能只减少源站流量,客户端仍要下载响应体;客户端直接复用缓存才符合上述“不重新传输”的条件。若目标是评估源站成本,应另建源站命中模型,不能沿用同一个百分比。

import math

def estimate(old_bytes, new_bytes, support, cache_hit, requests):
    if not all(math.isfinite(x) for x in (old_bytes, new_bytes, requests)):
        raise ValueError("Sizes and request count must be finite")
    if old_bytes <= 0 or new_bytes <= 0 or requests < 0:
        raise ValueError("Invalid size or request count")
    if not (0 <= support <= 1 and 0 <= cache_hit <= 1):
        raise ValueError("Fractions must be in [0, 1]")
    average = support * new_bytes + (1 - support) * old_bytes
    saved_per_transfer = old_bytes - average
    saved_total = requests * (1 - cache_hit) * saved_per_transfer
    return average, saved_total

average, saved = estimate(300_000, 210_000, 0.8, 0.6, 100_000)
assert math.isclose(average, 228_000)
assert math.isclose(saved, 2_880_000_000)
assert estimate(300_000, 210_000, 0, 0.6, 100_000)[1] == 0
assert estimate(300_000, 210_000, 0.8, 1, 100_000)[1] == 0
assert estimate(300_000, 330_000, 1, 0, 1)[1] < 0
for invalid in (math.nan, math.inf):
    try:
        estimate(invalid, 210_000, 0.8, 0.6, 100_000)
    except ValueError:
        pass
    else:
        raise AssertionError("Nonfinite size accepted")
print(f"Average bytes per body transfer: {average:.0f}")
print(f"Saved decimal GB: {saved / 1_000_000_000:.2f}")

原创 Python 示例已执行,核对228000字节、2.88 GB,以及不支持新格式、全部命中客户端缓存和新文件反而更大三个边界。它算的是条件模型,不执行图片编码、不跑浏览器基准,也不包含请求头、重验证或失败重试的流量。示例还拒绝非有限尺寸输入;每次计算为常数数量的算术运算。

下载省下的时间,不一定等于更早显示

单次减少90000字节,假设有效传输速度为每秒1000000字节,纯传输差额约90毫秒。但页面还需要发现图片地址、排队请求、解码并绘制。图片若根本不在首屏关键路径上,省下的传输时间可能更适合解释流量变化,而非首屏显示变化。多个请求还可能并行,不能把每张图片的90毫秒直接相加成页面提速。应查看所选图片何时被发现、是否阻塞关键显示,并与其他资源共同判断。

这不是说小文件无用,而是要找对因果链。测试时先固定图片尺寸和画质,再记录字节数、资源请求和实际显示情况。不同设备上的解码成本可能不同,不应拿一次桌面结果推广到所有手机。用户最终看到的图片是否更快、是否清楚,比某个压缩率更接近产品收益。

资源更小也不意味着搜索排名、阅读停留或打赏一定增长。可读性先做好:正文配图有明确图注,布局为图片留出空间,图片失效时文字仍能解释问题。然后才用合法可用的统计判断读者行为;没有真实访问或收款数据,就保留未知。

一个适合博客的小范围试验

选一张照片、一张含细字的截图和一张原创流程图,分别从同一原稿生成候选。保留旧文件,固定显示尺寸,对比图像质量与字节数。若候选没有优势,就不把它推广到这个素材类型;这比为统一格式接受更大文件更合理。

接着在测试页检查格式选择、地址有效性、响应 Content-Type 和缓存行为。最后才比较同样页面在目标桌面和手机上的显示体验。记录版本、参数、设备和浏览器,而不是只留一张“加载成功”的截图。失败时先回到原地址,再分别定位编码、选源与缓存问题。

今天的新闻使这项试验更值得考虑,但没有替你完成试验。对于希望通过技术内容建立长期信任的网站,能说明为什么采用、为什么暂缓,以及读者可以如何复查,比一句“全站升级最新格式”更有用。关于浏览器其他防护层,可以继续阅读Firefox 安全功能解读;它讨论的是账号与浏览行为,和本次图片部署不是同一个问题。

Read the English version

参考资料

支持

如果文中的解释或示例帮你解决了问题、节省了时间,欢迎自愿打赏支持本站。

微信支持二维码,点击查看大图
微信
支付宝支持二维码,点击查看大图
支付宝
Buy Me a Coffee,点击支持本站
Buy Me a Coffee

二维码可点击放大。更多支持方式见支持页面。

Share this Post

Leave a Comment

您的邮箱地址不会被公开。 必填项已用 * 标注

*
*