Skip to main content

Compression Middleware

Response compression middleware that negotiates br, gzip, and deflate from Accept-Encoding and applies sensible defaults for when compression is useful.

Installation

npm i remix

Function

compression()

Creates middleware that automatically compresses responses based on the client’s Accept-Encoding header and content type. Signature:
function compression(options?: CompressionOptions): Middleware
Parameters:
  • options - Optional compression settings
Returns: A middleware handler that automatically compresses responses.

Options

CompressionOptions

interface CompressionOptions {
  threshold?: number
  filterMediaType?: (mediaType: string) => boolean
  encodings?: Encoding[] | ((response: Response) => Encoding[])
  zlib?: ZlibOptions | ((response: Response) => ZlibOptions)
  brotli?: BrotliOptions | ((response: Response) => BrotliOptions)
}

threshold

Minimum size in bytes to compress (only enforced if Content-Length present).
  • Type: number
  • Default: 1024

filterMediaType

Optional filter to control which responses get compressed based on media type.
  • Type: (mediaType: string) => boolean
  • Default: Uses isCompressibleMimeType from @remix-run/mime

encodings

Which encodings the server supports for negotiation in order of preference.
  • Type: Encoding[] | ((response: Response) => Encoding[])
  • Default: ['br', 'gzip', 'deflate']
  • Values: 'br' | 'gzip' | 'deflate'

zlib

Node.js zlib options for gzip/deflate compression.
  • Type: ZlibOptions | ((response: Response) => ZlibOptions)
  • Default: Node.js defaults
  • See: Node.js zlib options

brotli

Node.js zlib options for Brotli compression.
  • Type: BrotliOptions | ((response: Response) => BrotliOptions)
  • Default: Node.js defaults
  • See: Node.js Brotli options

Basic Usage

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

let router = createRouter({
  middleware: [compression()],
})
The middleware automatically compresses responses when:
  • The client supports compression (Accept-Encoding header with a supported encoding)
  • The response is large enough (≥1024 bytes if Content-Length is present)
  • The response hasn’t already been compressed
  • The response doesn’t advertise range support (Accept-Ranges: bytes)

Custom Threshold

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

let router = createRouter({
  middleware: [
    compression({
      threshold: 2048, // Only compress responses ≥2KB
    }),
  ],
})

Custom Encodings

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

let router = createRouter({
  middleware: [
    compression({
      encodings: ['br', 'gzip'], // Only use Brotli and Gzip
    }),
  ],
})

Dynamic Encodings

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

let router = createRouter({
  middleware: [
    compression({
      encodings: (response) => {
        // Use different encodings for server-sent events
        let contentType = response.headers.get('Content-Type')
        return contentType?.startsWith('text/event-stream;')
          ? ['gzip', 'deflate']
          : ['br', 'gzip', 'deflate']
      },
    }),
  ],
})

Custom Media Type Filter

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

let router = createRouter({
  middleware: [
    compression({
      filterMediaType(mediaType) {
        // Add a custom media type to the default compressible list
        return isCompressibleMimeType(mediaType) || mediaType === 'application/vnd.example+data'
      },
    }),
  ],
})

Compression Options

import { createRouter } from 'remix/fetch-router'
import { compression } from 'remix/compression-middleware'
import { zlib } from 'node:zlib'

let router = createRouter({
  middleware: [
    compression({
      zlib: {
        level: 6,
      },
      brotli: {
        params: {
          [zlib.constants.BROTLI_PARAM_QUALITY]: 4,
        },
      },
    }),
  ],
})

Dynamic Compression Options

import zlib from 'node:zlib'
import { createRouter } from 'remix/fetch-router'
import { compression } from 'remix/compression-middleware'

let router = createRouter({
  middleware: [
    compression({
      brotli: (response) => {
        let contentType = response.headers.get('Content-Type')
        return {
          params: {
            [zlib.constants.BROTLI_PARAM_QUALITY]: contentType?.startsWith('text/html;') ? 4 : 11,
          },
        }
      },
    }),
  ],
})

Build docs developers (and LLMs) love