svelte icon indicating copy to clipboard operation
svelte copied to clipboard

import VERSION from svelte/compiler causes Cannot access "node:process.cwd" error

Open bhavers opened this issue 1 year ago • 1 comments

Describe the bug

In +layout.svelte i print the svelte and sveltekit version like this

import { VERSION as VERSION_SVELTE } from 'svelte/compiler';
import { VERSION } from '@sveltejs/kit';
console.log(`running svelte version ${VERSION_SVELTE} and SvelteKit version ${VERSION}`);

After migrating from svelte 4 to 5 (currently at 5.1.15) i get the following error in the console:

client.js:2682 Module "node:process" has been externalized for browser compatibility. Cannot access "node:process.cwd" in client code. See https://vite.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details.

This error is caused by the first import statement for the version of svelte. It does not stop execution, so just a minor nuisance.

Reproduction

  1. Create a new sveltekit project
  2. Add code to +layout.svelte
  3. Access the page.
  4. See error in Developer Tools console.

Logs

Full error message:
Module "node:process" has been externalized for browser compatibility. Cannot access "node:process.cwd" in client code. See https://vite.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details.
warn @ client.js:2682
get @ browser-external:node:process:9
(anonymous) @ validate-options.js:18

and first 19 lines of validate-options.js (it crashes on the line that starts with rootDir.

import process from 'node:process';

/** @import { ModuleCompileOptions, ValidatedModuleCompileOptions, CompileOptions, ValidatedCompileOptions } from '#compiler' */
import * as e from './errors.js';
import * as w from './warnings.js';

/**
 * @template [Input=any]
 * @template [Output=Input]
 * @typedef {(input: Input, keypath: string) => Required<Output>} Validator
 */

const common = {
    filename: string('(unknown)'),

    // default to process.cwd() where it exists to replicate svelte4 behavior
    // see https://github.com/sveltejs/svelte/blob/b62fc8c8fd2640c9b99168f01b9d958cb2f7574f/packages/svelte/src/compiler/compile/Component.js#L211
    rootDir: string(typeof process !== 'undefined' ? process.cwd?.() : undefined),

    dev: boolean(false),

System Info

System:
    OS: macOS 15.0.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 461.45 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 23.1.0 - /opt/homebrew/bin/node
    npm: 10.9.0 - /opt/homebrew/bin/npm
  Browsers:
    Brave Browser: 130.1.71.118
    Chrome: 130.0.6723.117 <--- browser tested in
    Safari: 18.0.1
  npmPackages:
    svelte: ^5.1.15 => 5.1.15

Severity

annoyance

bhavers avatar Nov 13 '24 22:11 bhavers

@benmccann you added these imports in #13204, but looking at the code where it's used (validate-options.js) it doesn't make sense to import it - the compiler is supposed to be node-agnostic, and there's a check to see if process exists, yet through the import it's likely always there? Is there any harm in removing this import?

dummdidumm avatar Nov 14 '24 12:11 dummdidumm

+1 to remove the import (possibly needs an eslint disable rule comment to prevent it from adding it back)

however this could break deno compatibility for users that use svelte without a bundler plugin that supplies rootDir compilerOption if they don't have a process global in deno2

dominikg avatar Nov 14 '24 14:11 dominikg

Yeah, I think I just added those all with eslint --fix, so I guess I missed that.

https://github.com/sveltejs/svelte/blob/320ebd24d8857570b0c180752765fb1580590367/packages/svelte/src/compiler/validate-options.js#L1

Yeah, looks like it should be removed. But we might have to also tweak it to keep Deno working like:

rootDir: typeof process !== 'undefined' ? process.cwd() : (typeof Deno !== undefined ? Deno.cwd() : undefined)

We could create a constant somewhere to hold the cwd, so that we can do this consistently if there are other places we need to use the cwd in the future

benmccann avatar Nov 14 '24 16:11 benmccann

'Deno' in window ?!!! that reads off. surely there is no window global on deno serverside?

const cwd_parent=typeof process !== 'undefined' ? process : (typeof Deno !== undefined ? Deno : undefined);
const cwd_value = typeof cwd_parent.cwd === 'function' ? cwd_parent.cwd() : undefined;

could work but do we want to add deno specific handling without adding Deno to our test matrix?

dominikg avatar Nov 14 '24 16:11 dominikg

to give users a chance to shim process.cwd if we don't want to do this, we'd have call get_cwd during compile instead of eagerly determining it on module load.

dominikg avatar Nov 14 '24 16:11 dominikg

I think you could simplify const cwd_value = typeof cwd_parent.cwd === 'function' ? cwd_parent.cwd() : undefined; to just const cwd_value = cwd_parent?.cwd();

I'm fine with adding Deno to the test matrix if folks would like to do that. I think we should try to support it regardless as it has quite a few users and it's a single line change to do so

benmccann avatar Nov 14 '24 16:11 benmccann