Node.js Compression Middleware

raw JSON →
1.8.4 verified Thu Apr 23 auth: no javascript

compression is a Node.js middleware designed for efficient HTTP response body compression, primarily utilized within web frameworks like Express.js. It supports multiple compression encodings, including deflate, gzip, and brotli, automatically negotiating the most suitable option with the client's `Accept-Encoding` header. The current stable version, 1.8.4, is actively maintained by the Express.js organization, receiving regular updates for security, dependency management, and minor improvements. Its release cadence is driven by the broader Express.js ecosystem's needs. Key differentiators include its simple API for integration into existing Express applications, extensive configuration options that leverage Node.js's native `zlib` module settings for granular control over compression levels and memory usage, and a flexible filter mechanism to conditionally apply compression based on request and response characteristics. It stands out for its robust handling of HTTP headers like `Cache-Control` to prevent unwanted transformations.

error Error: Cannot find module 'compression'
cause The 'compression' package has not been installed or is not accessible in the current project.
fix
Run npm install compression or yarn add compression in your project directory.
error Error: Can't set headers after they are sent to the client
cause The `compression` middleware attempted to modify response headers after they had already been sent to the client, typically because another middleware or route handler completed the response before `compression` could act.
fix
Ensure compression() middleware is applied early in your Express application's middleware stack, ideally before route definitions or any middleware that finalizes the response.
error Response content is not compressed (e.g., `Content-Encoding` header missing or not expected encoding)
cause Several reasons can prevent compression: the client did not send an `Accept-Encoding` header supporting the available algorithms, the response's `Content-Type` was not deemed compressible by the `filter` function, the `Cache-Control: no-transform` header was present, or the response size was below the `threshold`.
fix
Check the client's Accept-Encoding header. Verify your filter function's logic. Ensure no Cache-Control: no-transform header is sent. Adjust the threshold option to 0 to compress all responses if desired, or a small number like 1024 to compress small responses too.
gotcha Brotli compression (br) is only supported in Node.js versions v11.7.0 and v10.16.0 or newer. On older Node.js environments, Brotli will not be available even if specified.
fix Upgrade Node.js to a version that supports Brotli (e.g., 10.16.0+, 11.7.0+, 12.0.0+).
gotcha The middleware will explicitly skip compression for responses that include a `Cache-Control` header with the `no-transform` directive, as compressing would alter the body contrary to the directive.
fix Ensure that if you desire compression, your application does not send `Cache-Control: no-transform` headers. If you need `no-transform` for caching, consider if compression is appropriate for those specific responses.
gotcha Middleware order matters in Express. If `compression` is placed after routes or other middleware that send response headers, it will be unable to compress the response, leading to the 'Cannot set headers after they are sent' error.
fix Ensure `app.use(compression())` is placed early in your middleware chain, preferably before route definitions or any middleware that might send headers (e.g., `res.send()`, `res.json()`, `res.end()`).
npm install competion
yarn add competion
pnpm add competion

Demonstrates setting up an Express server with `compression` middleware, including basic configuration options like compression level, custom filtering, and size threshold. It also provides curl commands to test different compression scenarios.

import express from 'express';
import compression from 'compression';
import { createServer } from 'http';

const app = express();

// Apply compression middleware globally or to specific routes
app.use(compression({
  level: 6, // Default compression level (0-9)
  filter: (req, res) => {
    if (req.headers['x-no-compression']) {
      // Example: don't compress responses with 'x-no-compression' header
      return false;
    }
    // Fallback to the default filter function which checks Content-Type
    return compression.filter(req, res);
  },
  threshold: 0 // Compress all responses regardless of size (in bytes)
}));

app.get('/', (req, res) => {
  // A large enough response to demonstrate compression effectiveness
  const data = Array(5000).fill('This is some highly repetitive text that will compress extremely well.').join('');
  res.send(`<h1>Hello Compressed World!</h1><p>${data}</p>`);
});

const PORT = process.env.PORT || 3000;
const server = createServer(app);

server.listen(PORT, () => {
  console.log(`Server listening on http://localhost:${PORT}`);
  console.log('Test with cURL:');
  console.log(`  curl -H "Accept-Encoding: gzip" http://localhost:${PORT}/ -I`);
  console.log(`  curl -H "Accept-Encoding: br" http://localhost:${PORT}/ -I`);
  console.log(`  curl http://localhost:${PORT}/ -I`);
  console.log(`  curl -H "x-no-compression: true" -H "Accept-Encoding: gzip" http://localhost:${PORT}/ -I`);
});