nitro icon indicating copy to clipboard operation
nitro copied to clipboard

`useRuntimeConfig` does not inherits env variables without passing `env` param in cloudflare workers

Open pi0 opened this issue 1 year ago • 4 comments

Ref: https://github.com/nuxt/nuxt/issues/25047

In the cloudflare workers runtime, the useRuntimeConfig utility without passing explicit (event) parameter fallsback to the ambient context's value which because of cf limitation of env passed to first request, is not extended from env. (src)

Ideally event context should default to useEvent() however ironically CF is one of the only presets that does not have LocalAsyncStorage support out of the box.

To make DX better and consistent for CF users, we can reevaluate _sharedRuntimeConfig value after first request to make sure useRuntimeConfig() will be upgraded at least once.

Other alternative would be to disable caching for _sharedRuntimeConfig value at all. This has benefit of having synchronized runtime config even when running in ambient context but downside of less performance. (I will probably do this as is more straight forward and covering)

pi0 avatar Jan 05 '24 19:01 pi0

useRuntimeConfig(event) does not work at the moment in CF, nor does import.meta.env.NUXT_VAR, only process.env.NUXT_VAR.

I think @atinux also is experiencing this. Not sure if this is the same bug as here or if we should raise a new one, but it seems like a new regression.

cc: @pi0

danielroe avatar Apr 26 '24 09:04 danielroe

@danielroe i appreciate reproduction + new issue to investigate 🙏🏼

pi0 avatar Apr 29 '24 08:04 pi0

@pi0 @danielroe here is a great reproduction and overall test for envs on Cloudflare:

  • https://github.com/Atinux/nuxt-env-repro

But from what I see and test, it works as it should. Either I'm missing information or it was a temporary problem with Cloudflare.

I also checked my production applications and it works fine.

oritwoen avatar Apr 29 '24 12:04 oritwoen

I am using nitropack 2.9.6 and useRuntimeConfig() works fine without passing explicit (event). I think this one can be closed, as @oritwoen also reported it works fine?

However there is another issue that variables starting with NITRO_ are not passed automatically into runtimeConfig as expected: https://github.com/unjs/nitro/issues/2468

MickL avatar May 24 '24 10:05 MickL

Could it possibly be a difference between using a node_compat environment? My test results say YES:

Update: my first comment did not consider that nodejs_compat automatically triggers v2 when compatibility_date is set to a date on or after 2024-09-23. Now, that is corrected.

Note, I did the tests inside a Nuxt3 project. But I assume this is the upstream issue to write this information.

Output from a deploy with compatibility_flags = ["nodejs_compat"] in the wrangler.toml:

Important: if you set nodejs_compat and a compatibility_date on or after 2024-09-23 it will automatically upgrade to nodejs_compat_v2 and thus trigger the output of the next example.

{
	"runtimeConfig().hello": "config-defined-value", // this is the same value I defined in the nuxt.config.ts
	"runtimeConfig(event).hello": "pages secret defined value", // this is the value I defined via wrangler pages secret put
	"process.env.NUXT_HELLO": "pages secret defined value" // this is the value I defined via wrangler pages secret put
}

Output from a deploy with compatibility_flags = ["nodejs_compat_v2"] in the wrangler.toml:

This is the same for nodejs_compat_v2 and when you set nodejs_compat but also a compatibility_date on or after 2024-09-23.

{
	"runtimeConfig().hello": "config-defined-value", // this is the same value I defined in the nuxt.config.ts
	"runtimeConfig(event).hello": "config-defined-value" // this is the same value I defined in the nuxt.config.ts
}

Output from a deploy where I removed the ~~compatibility_flags = ["nodejs_compat_v2"]~~ in the wrangler.toml:

{
	"runtimeConfig().hello": "config-defined-value", // this is the same value I defined in the nuxt.config.ts
	"runtimeConfig(event).hello": "pages secret defined value", // this is the value I defined via wrangler pages secret put
	"process.env.NUXT_HELLO": "pages secret defined value" // this is the value I defined via wrangler pages secret put
}

So, this result indicates that node_compat_v2 as of now (2025-02-28) is not supported when using the useRuntimeConfig(event) method. This would also explain why it works for some and not for others.

The two variants that got it working are:

  1. Do not use nodejs_compat mode.
  2. Use nodejs_compat mode but with a compatibility_date that is 2024-09-22 or before (because any date after that automatically triggers nodejs_compat_v2.

Working wrangler.toml:

compatibility_date = "2024-09-22"
compatibility_flags = ["nodejs_compat"]

Future work:

I hope someone with more "under-the-hood-knowledge" can look into this and get this supported for pages/workers with the node_compat modes.

chrisspiegl avatar Feb 28 '25 16:02 chrisspiegl

@chrisspiegl Nitro 2.11 will natively support Cloudflare Node.js compatibility and you can remove compatibility_flags for it altogether.

It is a complicated story. There are 2 definitions of "Node.js compact" in cloudflare (native support in cloudflare workers platforms and incompatible transforms wrangler or cloudflare pages used to add).

pi0 avatar Feb 28 '25 16:02 pi0

The reason for me to use the compatibility_flags is actually not nitro or nuxt but rather some crypto libraries I am using. Which leads to me needing it anyway. But the results of my tests show that the useRuntimeConfig() behaves in different ways depending on the nodejs_compat modes.

P.S. I tried installing the nitropack-nightly to do a deploy (to see if it would be able to read the useRuntimeConfig(event) stuff. But sadly with the same result as above (nodejs_compat + a recent compatibility_date breaks it).

chrisspiegl avatar Feb 28 '25 16:02 chrisspiegl

Unfortunately crypto is a VERY bad idea on Cloudflare workers, at least with JS. I already got into that topic. BUT there is a solution, which is making another worker that runs Rust and your crypto library (argon2 I guess?). This other worker can be seamlessly connected to your existing JavaScript worker and be called from within your Nitro app.

Here is the package for the worker: https://github.com/glotlabs/argon2-cloudflare

I think this is called service binding, and you can call the Rust worker kinda like this:

await env.WORKER_B.fetch(request);

MickL avatar Feb 28 '25 16:02 MickL

Not my use case for crypto, and I am using crypto-js. But in my experience, there are tones of reasons to use nodejs_compat and I'd hope that nitro can support this environment as well.

I just had a hunch on why this useRuntimeConfig(event) stuff is not available for some people and is working for others. I hope that this information helps in the development of nitro to bring support for nodejs_compat_v2 into the system.

chrisspiegl avatar Feb 28 '25 17:02 chrisspiegl