1.4.1: nested pages dirs, CommonJS require of react in client bundles
- Page URL paths are now relative to src/pages. The old greedy
`.*/pages/` cut mapped src/pages/admin/pages/index.tsx to /index, so
every page under a nested `pages` directory collided with the home page
and was never bundled. SSR also tells API routes by URL path now.
- CommonJS `require("react…")` in client bundles (for example
use-sync-external-store/shim, pulled in by MUI) threw "Dynamic require
of "react" is not supported" in the browser. Those requires now go
through a small bundled ESM module that imports the external.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import * as esbuild from "esbuild";
|
||||
import type { BundlerCTXMap } from "../../types";
|
||||
type Params = {
|
||||
post_build_fn?: (params: {
|
||||
@@ -17,4 +18,13 @@ type Params = {
|
||||
*/
|
||||
export declare function isHydrationEntryPage(local_path: string): boolean;
|
||||
export default function allPagesESBuildContextBundler(params?: Params): Promise<void>;
|
||||
/**
|
||||
* CommonJS `require("react")` (e.g. `use-sync-external-store/shim`, pulled
|
||||
* in by MUI) for a module that is external in ESM output becomes esbuild's
|
||||
* `__require`, which throws "Dynamic require of "react" is not supported" in
|
||||
* the browser. Give those requires a small bundled ESM module that imports
|
||||
* the external instead; esbuild wires `require()` to it.
|
||||
*/
|
||||
export declare function externalRequireShim(specifier: string): string;
|
||||
export declare function forceExternalReact(): esbuild.Plugin;
|
||||
export {};
|
||||
|
||||
+27
-1
@@ -128,18 +128,44 @@ export default async function allPagesESBuildContextBundler(params) {
|
||||
], (line) => log.error(line));
|
||||
}
|
||||
}
|
||||
function forceExternalReact() {
|
||||
const ExternalRequireNamespace = "bunext-external-require";
|
||||
/**
|
||||
* CommonJS `require("react")` (e.g. `use-sync-external-store/shim`, pulled
|
||||
* in by MUI) for a module that is external in ESM output becomes esbuild's
|
||||
* `__require`, which throws "Dynamic require of "react" is not supported" in
|
||||
* the browser. Give those requires a small bundled ESM module that imports
|
||||
* the external instead; esbuild wires `require()` to it.
|
||||
*/
|
||||
export function externalRequireShim(specifier) {
|
||||
const spec = JSON.stringify(specifier);
|
||||
// A namespace import never fails to link, even when the vendor module has
|
||||
// no default export (jsx-runtime); fall back to the namespace for
|
||||
// `require(...).default` (Babel interop).
|
||||
return [
|
||||
`import * as ns from ${spec};`,
|
||||
`export * from ${spec};`,
|
||||
`export default ns.default ?? ns;`,
|
||||
].join("\n");
|
||||
}
|
||||
export function forceExternalReact() {
|
||||
return {
|
||||
name: "force-external-react",
|
||||
setup(build) {
|
||||
build.onResolve({ filter: /^react(-dom)?(\/.*)?$/ }, (args) => {
|
||||
if (args.pluginData?.externalReact)
|
||||
return null;
|
||||
if (args.kind === "require-call") {
|
||||
return { path: args.path, namespace: ExternalRequireNamespace };
|
||||
}
|
||||
return {
|
||||
path: args.path,
|
||||
external: true,
|
||||
};
|
||||
});
|
||||
build.onLoad({ filter: /.*/, namespace: ExternalRequireNamespace }, (args) => ({
|
||||
contents: externalRequireShim(args.path),
|
||||
loader: "js",
|
||||
}));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ async function computeEntryToPage() {
|
||||
}
|
||||
catch (error) { }
|
||||
for (const page of pages) {
|
||||
if (page.local_path.match(/\/pages\/api\//) ||
|
||||
if (page.url_path.startsWith("/api/") ||
|
||||
page.local_path.match(/\.server\.tsx?$/)) {
|
||||
const ts = await Bun.file(page.local_path).text();
|
||||
if (ts.match(/(export default)|(export \w+ handler)|(export \w+ server)/)) {
|
||||
|
||||
Reference in New Issue
Block a user