h3-compression icon indicating copy to clipboard operation
h3-compression copied to clipboard

Compression with Nuxt swr cache

Open YannickArmspach opened this issue 2 years ago • 8 comments

Environment

  • Operating System: Darwin
  • Node Version: v18.16.0
  • Nuxt Version: 3.8.2
  • CLI Version: 3.10.0
  • Nitro Version: 2.8.1
  • Package Manager: [email protected]
  • Builder: -
  • User Config: app, nitro, srcDir, runtimeConfig, extends, modules, ui, colorMode, googleFonts, fontMetrics, css, routeRules, telemetry, devtools, typescript
  • Runtime Modules: @nuxt/ui, @nuxtjs/fontaine@^0.4.1, @nuxtjs/google-fonts@^3.1.1, nuxt-og-image@^2.2.4, @linotype/nuxt@*
  • Build Modules: -

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 avatar Dec 12 '23 13:12 YannickArmspach

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 ?

YannickArmspach avatar Dec 12 '23 14:12 YannickArmspach

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.

CodeDredd avatar May 05 '24 12:05 CodeDredd

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.

bernhardberger avatar Jul 18 '24 23:07 bernhardberger

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).

infabo avatar Jul 23 '24 06:07 infabo

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.

bernhardberger avatar Jul 23 '24 07:07 bernhardberger

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.

CodeDredd avatar Jul 23 '24 14:07 CodeDredd

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?

bernhardberger avatar Jul 23 '24 14:07 bernhardberger

@CodeDredd using beforeResponse with useCompressionSteam does not work for me with SWR cache on Nuxt v3.13.2. I have to revert to useCompression.

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.

andrewspy avatar Oct 05 '24 11:10 andrewspy