Appearance
Using Route Cache with Compression
It is possible to use the route cache together with compression, such as with the h3-fast-compression or h3-compression library. You may compress both Nuxt-rendered pages or responses from server handlers.
WARNING
There are differences in performance with these two libraries and using h3-fast-compression
is recommended. See this issue for more information.
However, due to the way that both this module and these libraries work, you can not use compression within the event handler, for the simple reason that your event handler is only called once when the response is stored in cache. Afterwards the cached response is returned immediately. Of course you can still continue to use compression in an event handler, but just not together with the route cache.
For this reason, you have to compress responses globally, via the beforeResponse
Nitro hook. This is the only hook that is guaranteed to work; using render:response
will not work, because this hook is only called on the first render of the route.
INFO
While you can use compression from within your app like that, an alternative approach would be to handle this directly on your web server, using mod_deflate for Apache or by setting gzip on
in nginx.
Example
Only compress specific routes
typescript
import { useCompression } from 'h3-fast-compression'
import { getRequestURL } from 'h3'
import { defineNitroPlugin } from 'nitropack/runtime'
export default defineNitroPlugin((nitro) => {
nitro.hooks.hook('beforeResponse', async (event, response) => {
const url = getRequestURL(event)
// Prevent some paths from being compressed.
if (url.pathname.startsWith('/no-compression')) {
return
}
await useCompression(event, response)
})
})
Only compress specific content types
typescript
import { useCompression } from 'h3-fast-compression'
import { getRequestURL } from 'h3'
import { defineNitroPlugin } from 'nitropack/runtime'
export default defineNitroPlugin((nitro) => {
nitro.hooks.hook('beforeResponse', async (event, response) => {
const headerValue = getResponseHeader(event, 'content-type')
const contentType = Array.isArray(headerValue) ? headerValue : [headerValue]
const isApplicable = contentType.find(
(v) => typeof v === 'string' && v.includes('text/html'),
)
if (isApplicable) {
await useCompression(event, response)
}
})
})