Skip to content

Add Shared Brotli and Shared Zstandard (zstd)  #353

@summercms

Description

@summercms

This feature adds support for using designated previous responses, as an external dictionary for Brotli(or Zstandard)-compressing HTTP responses.

If the browser and server share a dictionary, using the dictionary for compression can significantly reduce the amount of data transferred. This is especially useful for incremental library updates, or when browsing multiple pages that have a lot of common parts in their files.

Compression Ratio Comparison Tests

format byte ratio
html 27278 100%
br 5453 20%
sbr 4559 17%

Browser Support

  • Shared Zstandard support is available on Google Chrome 118 onwards.
  • Firefox: Positive
  • Safari: No signal

Chrome 118

image

image

Chrome 117

The following flags were enabled on Chrome Canary 117.0.5912.0 and the behaviour was verified.

#enable-compression-dictionary-transport
#enable-compression-dictionary-transport-backend

Demos and samples

https://compression-dictionary-transport-threejs-demo.glitch.me/
https://compression-dictionary-transport-shop-demo.glitch.me/

Info

https://github.com/WICG/compression-dictionary-transport
https://datatracker.ietf.org/doc/draft-meenan-httpbis-compression-dictionary
https://docs.google.com/document/d/1IcRHLv-e9boECgPA5J4t8NDv9FPHDGgn0C12kfBgANg/edit#heading=h.7nki9mck5t64
https://github.com/facebook/zstd
https://en.wikipedia.org/wiki/Zstd

Examples

Bundled JavaScript on separate origin

In this example, www.example.com will use a bundle of application JavaScript that they serve from a separate static domain (static.example.com). The JavaScript files are versioned and have a long cache time, with the URL changing when a new version of the code is shipped.

On the initial visit to the site:

  • The browser loads https://www.example.com/ which contains <script src="//static.example.com/app/main.js/123" crossorigin> (where 123 is the build number of the code).
  • The browser requests https://static.example.com/app/main.js/123 with Accept-Encoding: sbr,br,gzip.
  • The server for static.example.com responds with the file as well as use-as-dictionary: match="/app/main.js*", Access-Control-Allow-Origin: https://www.example.com and Vary: Accept-Encoding,sec-available-dictionary.
  • The browser caches the js file along with a SHA-256 hash of the decompressed file and the https://www.example.com/app/main.js* URL pattern.
sequenceDiagram
Browser->>www.example.com: GET /
www.example.com->>Browser: ...<script src="//static.example.com/app/main.js/123" crossorigin>...
Browser->>static.example.com: GET /app/main.js/123<br/>Accept-Encoding: sbr,br,gzip
static.example.com->>Browser: use-as-dictionary: match="/app/main.js"<br/>Access-Control-Allow-Origin: https://www.example.com<br/>Vary: Accept-Encoding,sec-available-dictionary
Loading

At build time, the site developer creates delta-compressed versions of main.js using previous builds as dictionaries, storing the delta-compressed version along with the SHA-256 hash of the dictionary used (e.g. as main.js.<hash>.sbr).

On a future visit to the site after the application code has changed:

  • The browser loads https://www.example.com/ which contains <script src="//static.example.com/app/main.js/125" crossorigin>.
  • The browser matches the https://www.example.com/app/main.js/125 request with the https://www.example.com/app/main.js* URL pattern of the previous dictionary response that is in cache and requests https://static.example.com/app/main.js/125 with Accept-Encoding: sbr,br,gzip, sec-fetch-mode: cors and sec-available-dictionary: <SHA-256 HASH>.
  • The server for static.example.com matches the URL and hash with the pre-compressed artifact from the build and responds with it and Content-Encoding: sbr, Access-Control-Allow-Origin: https://www.example.com, Vary: Accept-Encoding,sec-available-dictionary.

It could have also included a new use-as-dictionary: match="/app/main.js*" response header to have the new version of the file replace the old one as the dictionary to use for future requests for the path but that is not a requirement for the existing dictionary to have been used.

sequenceDiagram
Browser->>www.example.com: GET /
www.example.com->>Browser: ...<script src="//static.example.com/app/main.js/125" crossorigin>...
Browser->>static.example.com: GET /app/main.js/125<br/>Accept-Encoding: sbr,br,gzip<br/>sec-fetch-mode: cors<br/>sec-available-dictionary: [SHA-256 HASH]
static.example.com->>Browser: Content-Encoding: sbr<br/>Access-Control-Allow-Origin: https://www.example.com<br/>Vary: Accept-Encoding,sec-available-dictionary
Loading

Site-specific dictionary used for all document navigations in a part of the site

In this example, www.example.com has a custom-built dictionary that should be used for all navigation requests to /product.

On the initial visit to the site:

  • The browser loads https://www.example.com/ which contains <link rel=dictionary href="/dictionaries/product_v1.dat">.
  • At an idle time, the browser sends an uncredentialed fetch request for https://www.example.com/dictionaries/product_v1.dat.
  • The server for www.example.com responds with the dictionary contents as well as use-as-dictionary: match="/product/*" and appropriate caching headers.
  • The browser caches the dictionary file along with a SHA-256 hash of the decompressed file and the https://www.example.com/product/* URL pattern.
sequenceDiagram
Browser->>www.example.com: GET /
www.example.com->>Browser: ...<link rel=dictionary href="/dictionaries/product_v1.dat">...
Browser->>www.example.com: GET /dictionaries/product_v1.dat<br/>Accept-Encoding: sbr,br,gzip
www.example.com->>Browser: use-as-dictionary: match="/product/*"
Loading

At some point after the dictionary has been fetched, the user clicks on a link to https://www.example.com/product/myproduct:

  • The browser matches the /product/myproduct request with the https://www.example.com/product/* URL pattern of the previous dictionary request and requests https://www.example.com/product/myproduct with Accept-Encoding: sbr,br,gzip and sec-available-dictionary: <SHA-256 HASH>.
  • The server supports dynamically compressing responses using available dictionaries and has the dictionary with the same hash available and responds with a brotli-compressed version of the response using the specified dictionary and Content-Encoding: sbr (and Vary headers if the response is cacheable).
sequenceDiagram
Browser->>www.example.com: GET /product/myproduct<br/>Accept-Encoding: sbr,br,gzip<br/>sec-available-dictionary: [SHA-256 HASH]
www.example.com->>Browser: Content-Encoding: sbr
Loading

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requeston-holdWaiting for something external to be done, like software release or official standard

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions