Firefox 158: Deploying JPEG XL

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

Firefox 158 enables JPEG XL by default, giving websites another image format they can deliver directly. It is worth testing, but a site-wide replacement is premature. Keep a compatible fallback, compare samples at equivalent quality, and check caching and decoding before deciding whether visitors actually benefit.

Contents
  1. What changed, and when
  2. Three meanings of losslessness
  3. Start with explicit format URLs
  4. Negotiating one URL also involves the cache
  5. Translate file savings into a delivery model
  6. Less transfer time need not mean earlier display
  7. A manageable blog experiment
  8. Sources

What changed, and when

The Linuxiac report discovered through Google News is dated October 12. Mozilla lists October 13, 2026 as Firefox 158’s Release-channel date. Those describe different milestones: an early report that files are available should not replace the official channel date. This article follows the published release and developer documentation.

MDN’s Firefox 158 notes confirm default JPEG XL support and the addition of image/jxl to the default Accept header for image requests. Decoding support matters on the client; the header matters when a server chooses a representation. Together, they create a deployment opportunity rather than completing a deployment.

The question here is how to deliver photographs, screenshots and article illustrations. Older versions, embedded browsers and devices that have not updated cannot be declared compatible merely because Firefox added support. For an illustrated blog, a limited comparison is a better first step than replacing payment QR codes or every historical asset.

Three meanings of losslessness

JPEG XL supports lossy and lossless coding and lossless transcoding of existing JPEGs. Encoding original pixels without loss, choosing acceptable visual loss, and reconstructing an existing JPEG are different goals. The libjxl reference implementation provides encoding and decoding tools. Whether JPEG reconstruction information is preserved depends on the selected mode and options, not the extension.

A reversible conversion of a JPEG that was already lossy cannot restore camera data discarded earlier. It preserves existing content or coding information. Conversely, comparing an old large image with a new lossy image that lost detail does not isolate the format’s advantage.

Define the use first. Is some visual difference acceptable in a photograph? Are small screenshot labels legible? Are transparent edges correct, and are color handling and target devices consistent? Inspect thin lines and numerals in diagrams rather than judging only a thumbnail. An encoder quality number is not an equivalent-quality setting across formats.

A useful comparison fixes content and display dimensions, keeps the original, and records encoder version, options and output bytes before inspecting the result. Without those conditions, an attractive percentage is insufficient evidence for migration. The numbers below demonstrate a method; they do not substitute a vendor’s generic ratio for measurements of your assets.

Start with explicit format URLs

A straightforward path for a small site is to give the same content separate JXL and compatible-format URLs. HTML picture uses a source type to help choose the format; MDN documents the selection rules.

Same image content
↓
Browser supports image/jxl?
Yes → choose .jxl source
No → use the .jpg img
Fetch selected URL → decode → display
Original selection flow. Format support is a selection condition, not a recovery mechanism for a failed selected URL.
<picture>
  <source srcset="/images/diagram-1200.jxl" type="image/jxl">
  <img src="/images/diagram-1200.jpg"
       width="1200" height="800"
       alt="Image delivery architecture"
       style="max-width:100%;height:auto">
</picture>

These are illustrative deployment paths. Replace them with generated, accessible files before use. The img supplies the content description and dimensions, while source supplies a format candidate. Width and height should preserve the asset’s ratio. Alt text describes what the illustration communicates rather than listing format names or SEO keywords.

This fallback addresses an unsupported candidate format. If the browser selected JXL but its URL returns 404, an incorrect content type or damaged data, do not assume automatic recovery to JPEG. Open both assets, inspect their responses, and confirm selection in the target environment that lacks the candidate’s support.

Start with a noncritical image, retain the original URL, and inspect the selected resource and rendered page. Avoid turning the key page image, support QR codes and every old post into one experiment. Scannability and unchanged payment destinations matter more than saving bytes on support images.

Negotiating one URL also involves the cache

A server can instead return different encodings at one URL based on Accept. HTML stays simpler, but the server and CDN must understand that the same URL can produce different bodies. The Vary response header identifies request headers affecting representation selection. Accept-based negotiation generally needs Vary: Accept as well as a review of the cache service’s configuration.

A source-server header alone does not prove that the delivery chain is correct. CDNs, proxies and application caches may use their own variant rules. Caching a JXL response first and serving it to an incompatible client is a failure worth testing explicitly. Content-Type must also match the bytes; renaming a JPEG is not conversion.

The following comparison describes deployment tradeoffs, not guaranteed features of a particular CDN.

Path Benefit Main check
Separate format URLs Selection visible in HTML Each candidate needs a valid file
One negotiated URL One public URL Representation and cache keys must agree

Test both access orders: a supporting client followed by an incompatible one, then the reverse after clearing the test cache. A single successful request from one client cannot reveal mixed variants. Record cache hits and body transfers so that warming the cache is not mistaken for a format speedup.

Translate file savings into a delivery model

Assume the old image is 300 kB, the JXL candidate is 210 kB, and 80% of relevant deliveries can use the candidate. The rest retain the old format. Decimal kB means 1,000 bytes here. The successful candidate saves 30%, but the weighted mean is 0.8×210+0.2×300=228 kB: a 24% aggregate reduction.

Old format: 300 kB
JXL candidate: 210 kB
Weighted delivery: 228 kB
Original hypothetical size model. Decimal kB; 80% support assumed. These are not encoded-file measurements or a universal compression ratio.

Now assume 100,000 image requests, with 60% satisfied by effective client caching without another response-body transfer. The remaining 40,000 transfers save 72 kB each, or about 2.88 decimal GB. These assumptions are not this site’s traffic, browser distribution or revenue. Replace them with measured inputs and matching definitions before using the model commercially.

Cache location matters. A CDN hit may reduce origin traffic while the client still downloads the body. Direct client reuse matches the no-body-transfer assumption above. Estimating origin cost requires a separate origin-cache model rather than reusing the same percentage.

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}")

The original Python example was executed, checking 228,000 bytes, 2.88 GB, no format support, complete client-cache reuse, and a candidate larger than the original. It calculates a conditional model, not image encoding or a browser benchmark. Headers, revalidation and failed retries are excluded. It also rejects nonfinite size inputs. Each call performs a constant number of arithmetic operations.

Less transfer time need not mean earlier display

Saving 90,000 bytes at an assumed effective transfer rate of 1,000,000 bytes per second saves about 90 milliseconds of transfer. A page still has to discover the URL, schedule the request, decode and paint. An image outside the initial critical path may provide a traffic benefit without an equivalent improvement to the first visible page. Requests can also overlap: adding a hypothetical 90-millisecond saving for each image does not establish that the whole page becomes that much faster. Inspect when the chosen image is discovered and whether it delays a critical visible element alongside other resources.

This is a reason to identify the causal path, not dismiss smaller files. Fix dimensions and quality, then record bytes, resource requests and display behavior. Decoding costs can differ across devices; one desktop observation should not be generalized to every phone. Whether the image appears sooner and remains readable is closer to a product benefit than a compression ratio alone.

Smaller assets also do not establish better search rankings, engagement or tips. Make illustrations useful, reserve their layout space, and ensure the text still explains the subject if an image fails. Use authorized, available statistics to assess reader behavior afterward. Traffic or payment data that is unavailable remains unknown.

A manageable blog experiment

Select a photograph, a screenshot with fine text and an original flow diagram. Generate candidates from the same source, keep the old files, fix display dimensions and compare quality and bytes. If the candidate has no advantage for a category, leave that category alone rather than accepting larger files merely to standardize a format.

On a test page, check selection, URL validity, Content-Type and cache behavior. Only then compare display on target desktops and phones. Record versions, options, devices and browsers, not just a screenshot proving that something loaded. If a problem appears, restore the original delivery path and investigate encoding, selection and caching separately.

The release makes this experiment more relevant, but it does not perform the experiment for you. Explaining why to adopt, why to wait and how readers can reproduce the decision builds more confidence than announcing a blanket format upgrade. For other browser protection layers, see the Firefox security explanation; accounts and browsing behavior are a separate subject from image deployment.

阅读中文版

Sources

Support

If the explanations or examples helped you solve a problem or save time, you’re welcome to support this site with a voluntary tip.

WeChat support QR code; click to enlarge
WeChat
Alipay support QR code; click to enlarge
Alipay
Buy Me a Coffee; support this site
Buy Me a Coffee

Click a QR code to enlarge. More options: support page。

Share this Post

Leave a Comment

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

*
*