Skip to content

compression-middleware

The compression middleware compresses HTTP response bodies to reduce transfer size. It negotiates the best encoding with the client using the Accept-Encoding header and supports gzip, brotli, and deflate.

Installation

The compression middleware is included with Remix. No additional installation is needed.

Import

ts
import { compression } from 'remix/compression-middleware'

API

compression(options?)

Returns a middleware function that compresses response bodies.

ts
let router = createRouter({
  middleware: [
    compression(),
  ],
})

Options

OptionTypeDefaultDescription
thresholdnumber1024Minimum response size in bytes before compression is applied. Responses smaller than this are sent uncompressed.
encodingsstring[]['br', 'gzip', 'deflate']Ordered list of encodings to support. The first encoding that the client accepts is used.

Behavior

The middleware:

  1. Reads the Accept-Encoding header from the request.
  2. Selects the best supported encoding by comparing the client's preferences with the configured encodings list.
  3. After the handler produces a response, compresses the body if:
    • The response body is larger than threshold bytes.
    • The response does not already have a Content-Encoding header.
    • The Content-Type is compressible (text, JSON, HTML, SVG, JavaScript, CSS, etc.).
  4. Sets the Content-Encoding and Vary: Accept-Encoding headers on the compressed response.

The middleware respects Accept-Ranges headers. If a response includes Accept-Ranges: bytes (used for range requests, such as video streaming), compression is skipped to preserve byte-range semantics.

Examples

Basic Usage

ts
import { createRouter } from 'remix/fetch-router'
import { compression } from 'remix/compression-middleware'

let router = createRouter({
  middleware: [
    compression(),
  ],
})

Custom Threshold

Compress only responses larger than 2 KB:

ts
compression({
  threshold: 2048,
})

Limit Encodings

Support only gzip (for environments where brotli is unavailable):

ts
compression({
  encodings: ['gzip', 'deflate'],
})

Place compression() early in the middleware chain so it wraps responses from all downstream middleware and handlers:

ts
let router = createRouter({
  middleware: [
    logger(),
    compression(),
    staticFiles('./public'),
    csrf(),
    formData(),
  ],
})

Released under the MIT License.