From 81bfcdb4355ab93243c2bcf153c90f2f28fac870 Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Mon, 22 May 2023 11:54:17 +0100 Subject: [PATCH] fix built-in node modules static imports (#268) * allow any node built-in module to run correctly * add changeset --- .changeset/lucky-toys-confess.md | 16 +++++++++ src/buildApplication/generateFunctionsMap.ts | 37 +++++++++++--------- 2 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 .changeset/lucky-toys-confess.md diff --git a/.changeset/lucky-toys-confess.md b/.changeset/lucky-toys-confess.md new file mode 100644 index 000000000..9932efb2f --- /dev/null +++ b/.changeset/lucky-toys-confess.md @@ -0,0 +1,16 @@ +--- +'@cloudflare/next-on-pages': patch +--- + +allow any node built-in module to be statically imported correctly + +currently only static imports from "node:buffer" work correctly, other +imports, although supported by the workers runtime, aren't handled correctly +(such as "node:events" and "node:util"), fix this by making sure we handle +imports from any of the node built-in modules + +> **Note** +> some node built-in modules supported by the workers runtime still cannot be +> correctly imported (like "node:path" for example), but this is because they +> seem to be not allowed by vercel/next itself (so it's something unrelated to +> next-on-pages) diff --git a/src/buildApplication/generateFunctionsMap.ts b/src/buildApplication/generateFunctionsMap.ts index 9bcf4902b..d65de87f7 100644 --- a/src/buildApplication/generateFunctionsMap.ts +++ b/src/buildApplication/generateFunctionsMap.ts @@ -268,7 +268,7 @@ async function processFuncDirectory( bundle: true, external: ['node:*', `${relativeChunksPath}/*`, '*.wasm'], minify: true, - plugins: [nodeBufferPlugin], + plugins: [nodeBuiltInModulesPlugin], }); const formattedPathName = formatRoutePath(relativePath); const normalizedFilePath = normalizePath(newFilePath); @@ -478,7 +478,7 @@ async function buildWebpackChunkFiles( bundle: true, external: ['node:*'], minify: true, - plugins: [nodeBufferPlugin], + plugins: [nodeBuiltInModulesPlugin], }); const fileContents = await readFile(chunkFilePath, 'utf8'); const wasmChunkImports = Array.from(wasmIdentifiers.entries()) @@ -652,29 +652,34 @@ function getFunctionNestingLevel(functionPath: string): number { return nestingLevel; } -// Chunks can contain `require("node:buffer")`, this is not allowed and breaks at runtime -// the following fixes this by updating the require to a standard esm import from node:buffer -export const nodeBufferPlugin: Plugin = { - name: 'node:buffer', +// Chunks can contain `require("node:*")`, this is not allowed and breaks at runtime +// the following fixes this by updating the require to a standard esm import from "node:*" +export const nodeBuiltInModulesPlugin: Plugin = { + name: 'node:built-in:modules', setup(build) { - build.onResolve({ filter: /^node:buffer$/ }, ({ kind, path }) => { - // this plugin converts `require("node:buffer")` calls, those are the only ones that - // need updating (esm imports to "node:buffer" are totally valid), so here we tag with the + build.onResolve({ filter: /^node:/ }, ({ kind, path }) => { + // this plugin converts `require("node:*")` calls, those are the only ones that + // need updating (esm imports to "node:*" are totally valid), so here we tag with the // node-buffer namespace only imports that are require calls return kind === 'require-call' ? { path, - namespace: 'node-buffer', + namespace: 'node-built-in-modules', } : undefined; }); - // we convert the imports we tagged with the node-buffer namespace so that instead of `require("node:buffer")` - // they import from `export * from 'node:buffer;'` - build.onLoad({ filter: /.*/, namespace: 'node-buffer' }, () => ({ - contents: `export * from 'node:buffer'`, - loader: 'js', - })); + // we convert the imports we tagged with the node-built-in-modules namespace so that instead of `require("node:*")` + // they import from `export * from "node:*";` + build.onLoad( + { filter: /.*/, namespace: 'node-built-in-modules' }, + ({ path }) => { + return { + contents: `export * from '${path}'`, + loader: 'js', + }; + } + ); }, };