CodeDredd / h3-compression

Adds compression to h3 requests (brotli, gzip, deflate)
MIT License
68 stars 2 forks source link

Compression with Nuxt swr cache #5

Open YannickArmspach opened 9 months ago

YannickArmspach commented 9 months ago

Environment

Reproduction

https://github.com/YannickArmspach/nuxt3-h3-compression

Describe the bug

Hello,

I try to activate compression with Nuxt cache without success.

Compression works fine by default in nuxt (ssr) with NitroPlugin integration: image

But if I activate the nuxt cache (swr), the cache is returned but without compression: image

Is there another solution (hook?) to also compress the cache returned by nuxt?

Additional context

No response

Logs

No response

YannickArmspach commented 9 months ago

Okey, the solution was in my question :D it works with the "beforeResponse" hook:

nitro.hooks.hook('beforeResponse', async (event, response) => {
    await useCompression(event, response)
})

@CodeDredd This may be a better example for your documentation because it works with the cache. Not ?

CodeDredd commented 5 months ago

I think your idea sounds good. But i am no nitro expert. I don't know if that has any down sides using it that way.

bernhardberger commented 2 months ago

I think your idea sounds good. But i am no nitro expert. I don't know if that has any down sides using it that way.

in conjunction with another issue (swr not handling Buffer steams correctly, see [need to find link]) I think one would need to check first if the body in the response is a Buffer or serialized data as we wouldn't want to gzip binary data. I also think we should be careful not to touch the internal _nuxt routes.

Other than that I think it's fine.

PS: I agree, you need that hook with SWR. Might actually be the proper way to do it.

infabo commented 2 months ago

Okey, the solution was in my question :D it works with the "beforeResponse" hook:

nitro.hooks.hook('beforeResponse', async (event, response) => {
    await useCompression(event, response)
})

@CodeDredd This may be a better example for your documentation because it works with the cache. Not ?

Using the beforeResponse hook comes with one major drawback: it is executed on every single response. You don't notice on a powerful CPU. But we noticed that our response time went through the roof (150ms without -> 1200ms with compression).

bernhardberger commented 2 months ago

I think the reason it doesn't fire in SWR context is this:

https://github.com/CodeDredd/h3-compression/blob/main/src/helper.ts#L18

const encoding = getRequestHeader(event, 'accept-encoding')

Pretty sure SWR cache requests are without accept-encoding headers (which makes sense since they're basically server-side requests).

The proper way would probably to generate all 3 and then check in the nitro onBeforeResponse hook for client accept-encoding headers and return the cached version accordingly.

CodeDredd commented 2 months ago

When i got some time i am gonna try out what i see with swr. @bernhardberger I dont think generating all 3 compressions is a good idea since this costs resources.

Using the beforeResponse hook comes with one major drawback: it is executed on every single response. You don't notice on a powerful CPU. But we noticed that our response time went through the roof (150ms without -> 1200ms with compression).

If you use beforeResponse you can use useCompressionStream. I think this shouldn't impact response time that much.

bernhardberger commented 2 months ago

When i got some time i am gonna try out what i see with swr. @bernhardberger I dont think generating all 3 compressions is a good idea since this costs resources.

If you use beforeResponse you can use useCompressionStream. I think this shouldn't impact response time that much.

I think @infabo could share some insights here, maybe even to the extent of a PR?