Skip to content

Commit c45de7b

Browse files
committed
fix(vite): handle server builtins in deno
1 parent 0a47c4d commit c45de7b

4 files changed

Lines changed: 36 additions & 11 deletions

File tree

deno.lock

Lines changed: 2 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/plugin-vite/deno.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"imports": {
2424
"@babel/core": "npm:@babel/core@^7.28.0",
2525
"@babel/preset-react": "npm:@babel/preset-react@^7.27.1",
26-
"@deno/loader": "jsr:@deno/loader@^0.4.0",
26+
"@deno/loader": "jsr:@deno/loader@~0.3.10",
2727
"@marvinh-test/import-json": "jsr:@marvinh-test/import-json@^0.0.1",
2828
"@remix-run/node-fetch-server": "npm:@remix-run/node-fetch-server@^0.12.0",
2929
"@prefresh/vite": "npm:@prefresh/vite@^2.4.8",

packages/plugin-vite/src/mod.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ export function fresh(config?: FreshViteConfig): Plugin[] {
167167
},
168168
},
169169
ssr: {
170+
resolve: {
171+
builtins: [],
172+
},
170173
build: {
171174
manifest: true,
172175
emitAssets: true,

packages/plugin-vite/src/plugins/deno.ts

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { builtinModules } from "node:module";
1414
const { default: babelReact } = await import("@babel/preset-react");
1515

1616
const BUILTINS = new Set(builtinModules);
17+
const NODE_BUILTIN_PREFIX = "\0fresh-node-builtin::";
1718

1819
type LoaderModule = typeof import("@deno/loader");
1920

@@ -65,11 +66,13 @@ export function deno(): Plugin {
6566
return true;
6667
},
6768
async resolveId(id, importer, options) {
68-
if (BUILTINS.has(id)) {
69-
// `node:` prefix is not included in builtins list.
70-
if (!id.startsWith("node:")) {
71-
id = `node:${id}`;
69+
const builtin = id.startsWith("node:") ? id.slice("node:".length) : id;
70+
if (BUILTINS.has(builtin)) {
71+
id = id.startsWith("node:") ? id : `node:${id}`;
72+
if (this.environment.config.consumer === "server") {
73+
return NODE_BUILTIN_PREFIX + id;
7274
}
75+
// `node:` prefix is not included in builtins list.
7376
return {
7477
id,
7578
external: true,
@@ -179,6 +182,10 @@ export function deno(): Plugin {
179182
}
180183
},
181184
async load(id) {
185+
if (id.startsWith(NODE_BUILTIN_PREFIX)) {
186+
return nodeBuiltinModule(id.slice(NODE_BUILTIN_PREFIX.length));
187+
}
188+
182189
const loader = this.environment.config.consumer === "server"
183190
? ssrLoader
184191
: browserLoader;
@@ -399,6 +406,25 @@ function getDenoType(id: string, type: string): DenoRequestedModuleType {
399406
}
400407
}
401408

409+
async function nodeBuiltinModule(id: string) {
410+
const names = Object.keys(await import(id));
411+
return [
412+
`const mod = await Function("id", "return import(id)")(${
413+
JSON.stringify(id)
414+
});`,
415+
"const requireValue = mod.default ?? mod;",
416+
"export { requireValue as __require };",
417+
"export default requireValue;",
418+
...names
419+
.filter((name) =>
420+
/^[$_\p{ID_Start}][$_\u200c\u200d\p{ID_Continue}]*$/u
421+
.test(name)
422+
)
423+
.filter((name) => name !== "default")
424+
.map((name) => `export const ${name} = mod[${JSON.stringify(name)}];`),
425+
].join("\n");
426+
}
427+
402428
// Builds a 1:1 (line-by-line, column 0) source map so that Vite/V8 can
403429
// rewrite stack frames from `\0deno::{type}::{specifier}` virtual IDs back
404430
// to the original specifier. Uses an absolute URL/path in `sources` combined

0 commit comments

Comments
 (0)