Skip to content

Commit 3c19fdd

Browse files
bartlomiejuclaude
andcommitted
fix: restore noDiscovery and convert CJS require() to imports for client
The dependency optimizer causes duplicate preact instances when remote (JSR) islands resolve deps to /@fs/ paths while the optimizer bundles to /.vite/deps/. Restore noDiscovery: true to prevent this. For CJS packages used in client-side islands (like mime-db), convert require() calls to ESM import statements via regex so browsers can load them. The SSR shim continues to use Node.js createRequire. All tests pass: 36/36 dev, 31/31 build, 15/15 patches. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5c9ecc3 commit 3c19fdd

2 files changed

Lines changed: 42 additions & 25 deletions

File tree

packages/plugin-vite/src/mod.ts

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -150,23 +150,13 @@ export function fresh(config?: FreshViteConfig): Plugin[] {
150150
},
151151

152152
optimizeDeps: {
153-
// Exclude preact ecosystem from optimizer to prevent
154-
// duplicate instances with remote (JSR) islands. JSR
155-
// islands resolve deps to /@fs/ paths, so if the
156-
// optimizer also bundles them to /.vite/deps/, two
157-
// separate instances load. Other CJS packages (like
158-
// mime-db) are optimized normally.
159-
exclude: [
160-
"preact",
161-
"preact/hooks",
162-
"preact/jsx-runtime",
163-
"preact/jsx-dev-runtime",
164-
"preact/debug",
165-
"preact/compat",
166-
"@preact/signals",
167-
"@preact/signals-core",
168-
"preact-render-to-string",
169-
],
153+
// Disable dep optimizer because deno.ts handles all
154+
// module resolution. The optimizer causes duplicate
155+
// module instances when remote (JSR) islands resolve
156+
// deps to /@fs/ paths while the optimizer bundles to
157+
// /.vite/deps/. CJS packages in client-side islands
158+
// are handled by deno.ts's load hook.
159+
noDiscovery: true,
170160
},
171161

172162
publicDir: pathWithRoot(fConfig.staticDir[0], config.root),

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

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -206,23 +206,50 @@ export function deno(): Plugin {
206206
) {
207207
const isServer =
208208
this.environment.config.consumer === "server";
209-
const preamble = isServer
210-
? `import { createRequire as __cjs_createRequire } from "node:module";
209+
210+
if (isServer) {
211+
// SSR: use Node.js createRequire for full CJS compat
212+
const wrapped = `
213+
import { createRequire as __cjs_createRequire } from "node:module";
211214
import { fileURLToPath as __cjs_fileURLToPath } from "node:url";
212215
import { dirname as __cjs_dirname } from "node:path";
213216
var __filename = __cjs_fileURLToPath(import.meta.url);
214217
var __dirname = __cjs_dirname(__filename);
215-
var require = __cjs_createRequire(import.meta.url);`
216-
: `var __filename = "";
217-
var __dirname = "";
218-
var require = (id) => { throw new Error("require() not supported in browser: " + id); };`;
219-
220-
const wrapped = `${preamble}
218+
var require = __cjs_createRequire(import.meta.url);
221219
var module = { exports: {} };
222220
var exports = module.exports;
223221
224222
${code}
225223
224+
export default module.exports;
225+
`;
226+
return { code: wrapped };
227+
}
228+
229+
// Client: convert require() calls to ESM imports so
230+
// browsers can load them. Hoist static require() calls
231+
// to import statements at the top.
232+
const imports: string[] = [];
233+
let idx = 0;
234+
const transformed = code.replace(
235+
/\brequire\(["']([^"']+)["']\)/g,
236+
(_match: string, spec: string) => {
237+
const varName = `__cjs_import_${idx++}`;
238+
imports.push(
239+
`import ${varName} from ${JSON.stringify(spec)};`,
240+
);
241+
return `(${varName}.default ?? ${varName})`;
242+
},
243+
);
244+
245+
const wrapped = `${imports.join("\n")}
246+
var module = { exports: {} };
247+
var exports = module.exports;
248+
var __filename = "";
249+
var __dirname = "";
250+
251+
${transformed}
252+
226253
export default module.exports;
227254
`;
228255
return { code: wrapped };

0 commit comments

Comments
 (0)