Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sveltekit 2 + adapter-node 2 unable to disable prerender, '$env/dynamic/private' used in hooks.server.ts #11341

Closed
jonshipman opened this issue Dec 15, 2023 · 12 comments · Fixed by #11436

Comments

@jonshipman
Copy link

Describe the bug

Migration to SvelteKit 2, updated adapter-node to v2. Modified src/routes/+layout.server.ts to export const prerender = false; and added config.kit.prerender.crawl = false and config.kit.prerender.entries = [] to the svelte config.

Importing a dynamic $env/dynamic/private in hooks.server.ts because the variable is optional (typically use dynamic variables for items not strictly sensitive, e.g. username, hosts, ids, where the default value is committed to the repo).

import { env } from '$env/dynamic/private';

export const DBHOST = env.DBHOST || 'http://localhost:3067';

Interim fix: using process.env will work.

Reproduction

https://stackblitz.com/edit/envdynamicprivate?file=src%2Fhooks.server.js

Run npm run build to see the error message.

Logs

Error: Cannot read values from $env/dynamic/private while prerendering (attempted to read env.test). Use $env/static/private instead
    at _0x2e26db._evaluate (https://sveltejskittemplatedefaultvaof-yhpd.w-corp.staticblitz.com/blitz.a2aabdd9.js:352:376700)
    at async ModuleJob.run (https://sveltejskittemplatedefaultvaof-yhpd.w-corp.staticblitz.com/blitz.a2aabdd9.js:181:2372)

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 18.18.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.4.2 - /usr/local/bin/npm
    pnpm: 8.10.5 - /usr/local/bin/pnpm
  npmPackages:
    @sveltejs/adapter-auto: ^3.0.0 => 3.0.0 
    @sveltejs/adapter-node: ^2.0.0 => 2.0.0 
    @sveltejs/kit: ^2.0.0 => 2.0.0 
    @sveltejs/vite-plugin-svelte: ^3.0.0 => 3.0.1 
    svelte: ^4.2.7 => 4.2.8 
    vite: ^5.0.3 => 5.0.9

Severity

annoyance

Additional Information

As stated, we can use process.env as a stop gap until this is resolved. My assumption is that the check for $env/dynamic/private needs to run after the declaration of prerender false. hooks.server.js loads before prerender value is established.

@eunukasiko
Copy link

process.env gives me undefined env vars

@jonshipman
Copy link
Author

jonshipman commented Dec 15, 2023

I'll need to test if there's another package allowing those to resolve for me. Or it could be the difference between vite preview and node build.

In either case, $env/dynamic/private should ultimately work if the whole app is set to prerender false (currently does not).

@ollema
Copy link

ollema commented Dec 16, 2023

(as expected, this error will also show up if you like me have imported some other module in your +hooks.server.ts which then tries to load something from $env/dynamic/private)

@ollema
Copy link

ollema commented Dec 16, 2023

probably caused by:
#11277

see this comment:
#11277 (comment)

@CaptainCodeman
Copy link
Contributor

You can use the building environment flag to avoid referencing the env value

import { building } from '$app/environment'
import { env } from '$env/dynamic/private';

const fallback = 'http://localhost:3067'
export const DBHOST = building ? fallback : env.DBHOST || 'http://localhost:3067'

Alternatively, you can avoid referencing it outside of the hooks handle function. i.e. don't declare the DBHOST constant, just use env.DBHOST where it's needed (and use a .env file for the localhost fallback / configuration.

@nstuyvesant
Copy link
Contributor

@CaptainCodeman - thanks for steering me to this issue. It was exactly my problem. I was going crazy trying to figure out what would need to be prerendered since my +layout.server.ts disabled it.

As @ollema experienced, I had a `import { query } from '$lib/server/db' in my hooks.server.ts. The db module naturally needs to get the database URL.

Using the $app/environment's building worked for me.

@marcusirgens
Copy link

marcusirgens commented Dec 19, 2023

Spent a while not resolving this today before checking GitHub. We've used a file lib/server/env.ts to keep used environment variables organized. This change pretty much breaks that "pattern", and it was both hard to figure out where the dependency chain started (nothing in the stack trace from the build step) and to understand how we're supposed to use environment variables now (which is how we pass runtime config to our application).

Thanks @CaptainCodeman for the fix.

@nstuyvesant
Copy link
Contributor

I agree it would have been helpful to see hooks in the stack trace. Would have helped me find the problem.

@CaptainCodeman
Copy link
Contributor

CaptainCodeman commented Dec 19, 2023

Personally, I think any .server code should be able to access any env values, whatever combination of static / dynamic or public / private they are. It would make things a lot easier if the restriction was only applied to the client-side code.

I think it's fairly common to want to create clients for databases etc... based on env values, inside server hooks and server load fns. Having to add code to short circuit things just for the build risks introducing bugs because the code becomes more complex that it should really need to be.

The other solution is to lazy-initialize clients, inside hooks, so the reference isn't in any immediately imported code ... but again, it's extra complexity that I'd prefer to avoid.

@xmlking
Copy link

xmlking commented Dec 19, 2023

Spent a while not resolving this today before checking GitHub. We've used a file lib/server/env.ts to keep used environment variables organized. This change pretty much breaks that "pattern", and it was both hard to figure out where the dependency chain started (nothing in the stack trace from the build step) and to understand how we're supposed to use environment variables now (which is how we pass runtime config to our application).

Thanks @CaptainCodeman for the fix.

I have similar case https://github.com/xmlking/spectacular/blob/main/apps/console/src/lib/variables/variables.server.ts

@maietta
Copy link

maietta commented Dec 27, 2023

@CaptainCodeman - thanks for steering me to this issue. It was exactly my problem. I was going crazy trying to figure out what would need to be prerendered since my +layout.server.ts disabled it.

As @ollema experienced, I had a `import { query } from '$lib/server/db' in my hooks.server.ts. The db module naturally needs to get the database URL.

Using the $app/environment's building worked for me.

This solution doesn't work for me.

@maietta
Copy link

maietta commented Dec 27, 2023

Okay, so { env } and using env.DATABASE_URL instead of { DATABASE_URL } seems to fix the issue for me.

I am using SSR, the default rendering option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants