diff --git a/src/runtime/bake/config/transpiler.rs b/src/runtime/bake/config/transpiler.rs index 031283d76ba2..576c9eea0b19 100644 --- a/src/runtime/bake/config/transpiler.rs +++ b/src/runtime/bake/config/transpiler.rs @@ -47,6 +47,8 @@ impl Framework { out.options.out_extensions = bun_collections::StringHashMap::new(); out.options.hot_module_reloading = mode == Mode::Development; out.options.code_splitting = mode != Mode::Development; + // Server chunks are loaded from memory, where `import.meta.require` finds no chunk file. + out.options.split_require = false; // force disable filesystem output, even though bundle_v2 // is special cased to return before that code is reached. diff --git a/test/bake/dev/production.test.ts b/test/bake/dev/production.test.ts index 6771c0f96261..28d516eb89ff 100644 --- a/test/bake/dev/production.test.ts +++ b/test/bake/dev/production.test.ts @@ -703,6 +703,137 @@ export default function Counter() { expect(foundCounterBundle).toBe(true); }); + // Server chunks are loaded from memory, so the bundler must not print a + // require() of an ES module as a load of a sibling chunk file. One page per shape. + test.concurrent("server code can require() an ES module", async () => { + const dir = await tempDirWithBakeDeps("bake-production-require-esm", { + "src/index.tsx": `export default { app: { framework: "react" } };`, + + // A CommonJS file requires it. + "pages/index.tsx": `import { text } from "../lib/read.mjs"; +export default function Page() { + return

{text}

; +}`, + "lib/read.mjs": `import lib from "./index.cjs"; +export const text = "app: " + lib.version + " " + typeof lib.add;`, + "lib/index.cjs": `const esm = require("./esm.mjs"); module.exports = esm;`, + "lib/esm.mjs": `export const version = "1.2.3"; +export function add(a, b) { return a + b; } +export default { version: "the default object" };`, + + // The page requires it. + "pages/in-page.tsx": `const dep = require("../lib/in-page.ts"); +export default function Page() { + return

{"in-page: " + dep.version}

; +}`, + "lib/in-page.ts": `export const version = "1.2.3";`, + + // A function requires it, twice, during the render. It does not run before that. + "pages/lazy.tsx": `import { load } from "../lib/lazy.cjs"; +const before = typeof globalThis.lazyRuns; +export default function Page() { + const first = load(); + return

{"lazy: " + before + " " + first.version + " " + (first === load()) + " " + globalThis.lazyRuns}

; +}`, + "lib/lazy.cjs": `exports.load = () => require("./lazy-dep.mjs");`, + "lib/lazy-dep.mjs": `globalThis.lazyRuns = (globalThis.lazyRuns ?? 0) + 1; +export const version = "1.2.3";`, + + // A client component requires it (the SSR graph). + "pages/client.tsx": `import Client from "../lib/Client"; +export default function Page() { + return ; +}`, + "lib/Client.tsx": `"use client"; +const dep = require("./client-dep.ts"); +export default function Client() { + return

{"client: " + dep.version}

; +}`, + "lib/client-dep.ts": `export const version = "1.2.3";`, + + // It renders a client component. The page must load the client code. + "pages/island.tsx": `const { Island } = require("../lib/island.tsx"); +export default function Page() { + return ; +}`, + "lib/island.tsx": `import Button from "./Button"; +export function Island() { + return