Skip to content

CodeDredd/h3-compression

Repository files navigation

H3-compression

npm version npm downloads bundle JSDocs License

Handles compression for H3

Features

✔️  Zlib Compression: You can use zlib compression (brotli, gzip and deflate)

✔️  Stream Compression: You can use native stream compressions (gzip, deflate)

✔️  Compression Detection: It uses the best compression which is accepted

✔️  h3 v1 & v2: Works with both h3 v1 and v2

Install

# Using npm
npm install h3-compression

# Using yarn
yarn add h3-compression

# Using pnpm
pnpm add h3-compression

Usage (h3 v1)

import { createServer } from 'node:http'
import { createApp, eventHandler, toNodeListener } from 'h3'
import { useCompressionStream } from 'h3-compression'

const app = createApp({ onBeforeResponse: useCompressionStream }) // or { onBeforeResponse: useCompression }
app.use(
  '/',
  eventHandler(() => 'Hello world!'),
)

createServer(toNodeListener(app)).listen(process.env.PORT || 3000)

Example using listhen for an elegant listener:

import { createApp, eventHandler, toNodeListener } from 'h3'
import { listen } from 'listhen'
import { useCompressionStream } from 'h3-compression'

const app = createApp({ onBeforeResponse: useCompressionStream }) // or { onBeforeResponse: useCompression }
app.use(
  '/',
  eventHandler(() => 'Hello world!'),
)

listen(toNodeListener(app))

Usage (h3 v2)

In h3 v2 the response is an immutable web Response and the onBeforeResponse hook was removed. Use the compression / compressionStream middleware instead — they read the response returned by the next handler and replace it with a compressed one.

import { createServer } from 'node:http'
import { H3, toNodeHandler } from 'h3'
import { compression } from 'h3-compression'

const app = new H3()

app.use(compression()) // or app.use(compressionStream())
app.get('/', () => 'Hello world!')

createServer(toNodeHandler(app)).listen(process.env.PORT || 3000)

You can also force a specific method (e.g. compression('gzip')) instead of detecting it from the Accept-Encoding header.

Note

compressionStream uses the native CompressionStream, which only supports gzip and deflate (no brotli).

Nuxt 3 & 4

If you want to use it in Nuxt you can define a nitro plugin.

server/plugins/compression.ts

import { useCompression } from 'h3-compression'

export default defineNitroPlugin((nitro) => {
  nitro.hooks.hook('render:response', async (response, { event }) => {
    // Skip internal nuxt routes (e.g. error page)
    if (['/_nuxt', '/__nuxt'].some(prefix => getRequestURL(event).pathname.startsWith(prefix)))
      return

    if (!response.headers?.['content-type']?.startsWith('text/html'))
      return

    await useCompression(event, response)
  })
})

Note

useCompressionStream doesn't work right now in nitro. So you just can use useCompression

Cached routes (SWR / ISR) and /server/api

The render:response hook only runs for freshly rendered SSR pages. Responses served from the Nitro route cache (routeRules with swr / isr) and /server/api handlers go through the beforeResponse hook instead. Use it to compress those too:

server/plugins/compression.ts

import { useCompression } from 'h3-compression'

export default defineNitroPlugin((nitro) => {
  nitro.hooks.hook('beforeResponse', async (event, response) => {
    // Skip internal nuxt routes (e.g. error page)
    if (['/_nuxt', '/__nuxt'].some(prefix => event.path.startsWith(prefix)))
      return

    await useCompression(event, response)
  })
})

useCompression compresses string, Buffer/Uint8Array and JSON (object) bodies and skips everything else (e.g. streams), so binary assets are left untouched. If you only want to compress specific content types, guard on response.headers?.['content-type'] before calling it.

Utilities

H3-compression has a concept of composable utilities that accept event (from eventHandler((event) => {})) as their first argument and response as their second.

Zlib Compression

  • useGZipCompression(event, response)
  • useDeflateCompression(event, response)
  • useBrotliCompression(event, response)
  • useCompression(event, response)

Stream Compression

  • useGZipCompressionStream(event, response)
  • useDeflateCompressionStream(event, response)
  • useCompressionStream(event, response)

Middleware (h3 v2)

  • compression(method?)  – middleware using zlib (brotli, gzip, deflate)
  • compressionStream(method?)  – middleware using the native CompressionStream (gzip, deflate)
  • compressResponse(event, value, method?)  – low-level helper returning a compressed Response
  • compressResponseStream(event, value, method?)  – low-level stream helper returning a compressed Response

Sponsors

Releated Projects

License

MIT License © 2023-PRESENT Gregor Becker

About

Adds compression to h3 requests (brotli, gzip, deflate)

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Sponsor this project

 

Packages

 
 
 

Contributors

Generated from antfu/starter-ts