diff --git a/packages/cloudflare/src/cli/build/bundle-server.ts b/packages/cloudflare/src/cli/build/bundle-server.ts index c7c29387..82a2af78 100644 --- a/packages/cloudflare/src/cli/build/bundle-server.ts +++ b/packages/cloudflare/src/cli/build/bundle-server.ts @@ -8,6 +8,7 @@ import { getCrossPlatformPathRegex } from "@opennextjs/aws/utils/regex.js"; import { build, Plugin } from "esbuild"; import { patchVercelOgLibrary } from "./patches/ast/patch-vercel-og-library.js"; +import { patchWebpackRuntime } from "./patches/ast/webpack-runtime.js"; import * as patches from "./patches/index.js"; import { handleOptionalDependencies } from "./patches/plugins/optional-deps.js"; import { fixRequire } from "./patches/plugins/require.js"; @@ -49,7 +50,7 @@ export async function bundleServer(buildOpts: BuildOptions): Promise { console.log(`\x1b[35m⚙️ Bundling the OpenNext server...\n\x1b[0m`); - await patches.updateWebpackChunksFile(buildOpts); + await patchWebpackRuntime(buildOpts); patchVercelOgLibrary(buildOpts); const outputPath = path.join(outputDir, "server-functions", "default"); diff --git a/packages/cloudflare/src/cli/build/patches/ast/webpack-runtime.spec.ts b/packages/cloudflare/src/cli/build/patches/ast/webpack-runtime.spec.ts new file mode 100644 index 00000000..9ce03ad0 --- /dev/null +++ b/packages/cloudflare/src/cli/build/patches/ast/webpack-runtime.spec.ts @@ -0,0 +1,64 @@ +import { describe, expect, test } from "vitest"; + +import { patchCode } from "./util.js"; +import { buildInlineChunksRule } from "./webpack-runtime.js"; + +describe("webpack runtime", () => { + test("patch runtime", () => { + const code = ` + /******/ // require() chunk loading for javascript + /******/ __webpack_require__.f.require = (chunkId, promises) => { + /******/ // "1" is the signal for "already loaded" + /******/ if (!installedChunks[chunkId]) { + /******/ if (658 != chunkId) { + /******/ installChunk(require("./chunks/" + __webpack_require__.u(chunkId))); + /******/ + } else installedChunks[chunkId] = 1; + /******/ + } + /******/ + }; + `; + + expect(patchCode(code, buildInlineChunksRule([1, 2, 3]))).toMatchInlineSnapshot(` + "/******/ // require() chunk loading for javascript + /******/ __webpack_require__.f.require = (chunkId, _) => { + if (!installedChunks[chunkId]) { + switch (chunkId) { + case 1: installChunk(require("./chunks/1.js")); break; + case 2: installChunk(require("./chunks/2.js")); break; + case 3: installChunk(require("./chunks/3.js")); break; + case 658: installedChunks[chunkId] = 1; break; + default: throw new Error(\`Unknown chunk \${chunkId}\`); + } + } + } + ; + " + `); + }); + + test("patch minified runtime", () => { + const code = ` + t.f.require=(o,n)=>{e[o]||(658!=o?r(require("./chunks/"+t.u(o))):e[o]=1)} + `; + + expect(patchCode(code, buildInlineChunksRule([1, 2, 3]))).toMatchInlineSnapshot( + ` + "t.f.require=(o, _) => { + if (!e[o]) { + switch (o) { + case 1: r(require("./chunks/1.js")); break; + case 2: r(require("./chunks/2.js")); break; + case 3: r(require("./chunks/3.js")); break; + case 658: e[o] = 1; break; + default: throw new Error(\`Unknown chunk \${o}\`); + } + } + } + + " + ` + ); + }); +}); diff --git a/packages/cloudflare/src/cli/build/patches/ast/webpack-runtime.ts b/packages/cloudflare/src/cli/build/patches/ast/webpack-runtime.ts new file mode 100644 index 00000000..9818cd7f --- /dev/null +++ b/packages/cloudflare/src/cli/build/patches/ast/webpack-runtime.ts @@ -0,0 +1,70 @@ +/** + * Inline dynamic requires in the webpack runtime. + * + * The webpack runtime has dynamic requires that would not be bundled by ESBuild: + * + * installChunk(require("./chunks/" + __webpack_require__.u(chunkId))); + * + * This patch unrolls the dynamic require for all the existing chunks: + * + * switch (chunkId) { + * case ID1: installChunk(require("./chunks/ID1"); break; + * case ID2: installChunk(require("./chunks/ID2"); break; + * // ... + * case SELF_ID: installedChunks[chunkId] = 1; break; + * default: throw new Error(`Unknown chunk ${chunkId}`); + * } + */ + +import { readdirSync, readFileSync, writeFileSync } from "node:fs"; +import { join } from "node:path"; + +import { type BuildOptions, getPackagePath } from "@opennextjs/aws/build/helper.js"; + +import { patchCode } from "./util.js"; + +export function buildInlineChunksRule(chunks: number[]) { + return ` +rule: + pattern: ($CHUNK_ID, $_PROMISES) => { $$$ } + inside: {pattern: $_.$_.require = $$$_, stopBy: end} + all: + - has: {pattern: $INSTALL(require("./chunks/" + $$$)), stopBy: end} + - has: {pattern: $SELF_ID != $CHUNK_ID, stopBy: end} + - has: {pattern: "$INSTALLED_CHUNK[$CHUNK_ID] = 1", stopBy: end} +fix: | + ($CHUNK_ID, _) => { + if (!$INSTALLED_CHUNK[$CHUNK_ID]) { + switch ($CHUNK_ID) { +${chunks.map((chunk) => ` case ${chunk}: $INSTALL(require("./chunks/${chunk}.js")); break;`).join("\n")} + case $SELF_ID: $INSTALLED_CHUNK[$CHUNK_ID] = 1; break; + default: throw new Error(\`Unknown chunk \${$CHUNK_ID}\`); + } + } + }`; +} + +/** + * Fixes the webpack-runtime.js file by removing its webpack dynamic requires. + */ +export async function patchWebpackRuntime(buildOpts: BuildOptions) { + const { outputDir } = buildOpts; + + const dotNextServerDir = join( + outputDir, + "server-functions/default", + getPackagePath(buildOpts), + ".next/server" + ); + + const runtimeFile = join(dotNextServerDir, "webpack-runtime.js"); + const runtimeCode = readFileSync(runtimeFile, "utf-8"); + // Look for all the chunks. + const chunks = readdirSync(join(dotNextServerDir, "chunks")) + .filter((chunk) => /^\d+\.js$/.test(chunk)) + .map((chunk) => { + return Number(chunk.replace(/\.js$/, "")); + }); + + writeFileSync(runtimeFile, patchCode(runtimeCode, buildInlineChunksRule(chunks))); +} diff --git a/packages/cloudflare/src/cli/build/patches/investigated/index.ts b/packages/cloudflare/src/cli/build/patches/investigated/index.ts index 9d46a4d8..ddbc909f 100644 --- a/packages/cloudflare/src/cli/build/patches/investigated/index.ts +++ b/packages/cloudflare/src/cli/build/patches/investigated/index.ts @@ -1,4 +1,3 @@ export * from "./copy-package-cli-files.js"; export * from "./patch-cache.js"; export * from "./patch-require.js"; -export * from "./update-webpack-chunks-file/index.js"; diff --git a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-chunk-installation-identifiers.test.ts b/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-chunk-installation-identifiers.test.ts deleted file mode 100644 index 17435c63..00000000 --- a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-chunk-installation-identifiers.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { readFile } from "node:fs/promises"; - -import { describe, expect, test } from "vitest"; - -import { tsParseFile } from "../../../utils/index.js"; -import { getChunkInstallationIdentifiers } from "./get-chunk-installation-identifiers.js"; - -describe("getChunkInstallationIdentifiers", () => { - test("gets chunk identifiers from unminified code", async () => { - const fileContent = await readFile( - `${import.meta.dirname}/test-fixtures/unminified-webpacks-file.js`, - "utf8" - ); - const tsSourceFile = tsParseFile(fileContent); - const { installChunk, installedChunks } = await getChunkInstallationIdentifiers(tsSourceFile); - expect(installChunk).toEqual("installChunk"); - expect(installedChunks).toEqual("installedChunks"); - }); - - test("gets chunk identifiers from minified code", async () => { - const fileContent = await readFile( - `${import.meta.dirname}/test-fixtures/minified-webpacks-file.js`, - "utf8" - ); - const tsSourceFile = tsParseFile(fileContent); - const { installChunk, installedChunks } = await getChunkInstallationIdentifiers(tsSourceFile); - expect(installChunk).toEqual("r"); - expect(installedChunks).toEqual("e"); - }); -}); diff --git a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-chunk-installation-identifiers.ts b/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-chunk-installation-identifiers.ts deleted file mode 100644 index d7233066..00000000 --- a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-chunk-installation-identifiers.ts +++ /dev/null @@ -1,102 +0,0 @@ -import * as ts from "ts-morph"; - -/** - * Gets the names of the variables that in the unminified webpack runtime file are called `installedChunks` and `installChunk`. - * - * Variables example: https://github.com/webpack/webpack/blob/dae16ad11e/examples/module-worker/README.md?plain=1#L256-L282 - * - * @param sourceFile the webpack runtime file parsed with ts-morph - * @returns an object containing the two variable names - */ -export async function getChunkInstallationIdentifiers(sourceFile: ts.SourceFile): Promise<{ - installedChunks: string; - installChunk: string; -}> { - const installChunkDeclaration = getInstallChunkDeclaration(sourceFile); - const installedChunksDeclaration = getInstalledChunksDeclaration(sourceFile, installChunkDeclaration); - - return { - installChunk: installChunkDeclaration.getName(), - installedChunks: installedChunksDeclaration.getName(), - }; -} - -/** - * Gets the declaration for what in the unminified webpack runtime file is called `installChunk`(which is a function that registers the various chunks. - * - * `installChunk` example: https://github.com/webpack/webpack/blob/dae16ad11e/examples/module-worker/README.md?plain=1#L263-L282 - * - * @param sourceFile the webpack runtime file parsed with ts-morph - * @returns the `installChunk` declaration - */ -function getInstallChunkDeclaration(sourceFile: ts.SourceFile): ts.VariableDeclaration { - const installChunkDeclaration = sourceFile - .getDescendantsOfKind(ts.SyntaxKind.VariableDeclaration) - .find((declaration) => { - const arrowFunction = declaration.getInitializerIfKind(ts.SyntaxKind.ArrowFunction); - // we're looking for an arrow function - if (!arrowFunction) return false; - - const functionParameters = arrowFunction.getParameters(); - // the arrow function we're looking for has a single parameter (the chunkId) - if (functionParameters.length !== 1) return false; - - const arrowFunctionBodyBlock = arrowFunction.getFirstChildByKind(ts.SyntaxKind.Block); - - // the arrow function we're looking for has a block body - if (!arrowFunctionBodyBlock) return false; - - const statementKinds = arrowFunctionBodyBlock.getStatements().map((statement) => statement.getKind()); - - // the function we're looking for has 2 for loops (a standard one and a for-in one) - const forInStatements = statementKinds.filter((s) => s === ts.SyntaxKind.ForInStatement); - const forStatements = statementKinds.filter((s) => s === ts.SyntaxKind.ForStatement); - if (forInStatements.length !== 1 || forStatements.length !== 1) return false; - - // the function we're looking for accesses its parameter three times, and it - // accesses its `modules`, `ids` and `runtime` properties (in this order) - const parameterName = functionParameters[0]!.getText(); - const functionParameterAccessedProperties = arrowFunctionBodyBlock - .getDescendantsOfKind(ts.SyntaxKind.PropertyAccessExpression) - .filter( - (propertyAccessExpression) => propertyAccessExpression.getExpression().getText() === parameterName - ) - .map((propertyAccessExpression) => propertyAccessExpression.getName()); - if (functionParameterAccessedProperties.join(", ") !== "modules, ids, runtime") return false; - - return true; - }); - - if (!installChunkDeclaration) { - throw new Error("ERROR: unable to find the installChunk function declaration"); - } - - return installChunkDeclaration; -} - -/** - * Gets the declaration for what in the unminified webpack runtime file is called `installedChunks` which is an object that holds the various registered chunks. - * - * `installedChunks` example: https://github.com/webpack/webpack/blob/dae16ad11e/examples/module-worker/README.md?plain=1#L256-L261 - * - * @param sourceFile the webpack runtime file parsed with ts-morph - * @param installChunkDeclaration the declaration for the `installChunk` variable - * @returns the `installedChunks` declaration - */ -function getInstalledChunksDeclaration( - sourceFile: ts.SourceFile, - installChunkDeclaration: ts.VariableDeclaration -): ts.VariableDeclaration { - const allVariableDeclarations = sourceFile.getDescendantsOfKind(ts.SyntaxKind.VariableDeclaration); - const installChunkDeclarationIdx = allVariableDeclarations.findIndex( - (declaration) => declaration === installChunkDeclaration - ); - - // the installedChunks declaration comes right before the installChunk one - const installedChunksDeclaration = allVariableDeclarations[installChunkDeclarationIdx - 1]; - - if (!installedChunksDeclaration?.getInitializer()?.isKind(ts.SyntaxKind.ObjectLiteralExpression)) { - throw new Error("ERROR: unable to find the installedChunks declaration"); - } - return installedChunksDeclaration; -} diff --git a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-file-content-with-updated-webpack-f-require-code.test.ts b/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-file-content-with-updated-webpack-f-require-code.test.ts deleted file mode 100644 index 30eaf9b0..00000000 --- a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-file-content-with-updated-webpack-f-require-code.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { readFile } from "node:fs/promises"; - -import { describe, expect, test } from "vitest"; - -import { tsParseFile } from "../../../utils/index.js"; -import { getFileContentWithUpdatedWebpackFRequireCode } from "./get-file-content-with-updated-webpack-f-require-code"; - -describe("getFileContentWithUpdatedWebpackFRequireCode", () => { - test("returns the updated content of the f.require function from unminified webpack runtime code", async () => { - const fileContent = await readFile( - `${import.meta.dirname}/test-fixtures/unminified-webpacks-file.js`, - "utf8" - ); - const tsSourceFile = tsParseFile(fileContent); - const updatedFCode = await getFileContentWithUpdatedWebpackFRequireCode( - tsSourceFile, - { installChunk: "installChunk", installedChunks: "installedChunks" }, - ["658"] - ); - expect(unstyleCode(updatedFCode)).toContain(`if (installedChunks[chunkId]) { return; }`); - expect(unstyleCode(updatedFCode)).toContain( - `if (chunkId === 658) { return installChunk(require("./chunks/658.js")); }` - ); - expect(unstyleCode(updatedFCode)).not.toContain(`require("./chunks/" +`); - }); - - test("returns the updated content of the f.require function from minified webpack runtime code", async () => { - const fileContent = await readFile( - `${import.meta.dirname}/test-fixtures/minified-webpacks-file.js`, - "utf8" - ); - const tsSourceFile = tsParseFile(fileContent); - const updatedFCode = await getFileContentWithUpdatedWebpackFRequireCode( - tsSourceFile, - { installChunk: "r", installedChunks: "e" }, - ["658"] - ); - expect(unstyleCode(updatedFCode)).toContain("if (e[o]) { return; }"); - expect(unstyleCode(updatedFCode)).toContain(`if (o === 658) { return r(require("./chunks/658.js")); }`); - expect(unstyleCode(updatedFCode)).not.toContain(`require("./chunks/" +`); - }); -}); - -function unstyleCode(text: string): string { - return text.replace(/\n\s+/g, "\n").replace(/\n/g, " "); -} diff --git a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-file-content-with-updated-webpack-f-require-code.ts b/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-file-content-with-updated-webpack-f-require-code.ts deleted file mode 100644 index f047b3ce..00000000 --- a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-file-content-with-updated-webpack-f-require-code.ts +++ /dev/null @@ -1,100 +0,0 @@ -import * as ts from "ts-morph"; - -/** - * Updates the function that in the unminified webpack runtime file appears as `__webpack_require__.f.require` which is a function that - * installs chunks by importing/requiring them at runtime. - * - * `__webpack_require__.f.require` example: https://github.com/webpack/webpack/blob/dae16ad11e/examples/module-worker/README.md?plain=1#L284-L304 - * - * This function needs to be updated so that it requires chunks using the standard `require` function and not webpack's custom `require` logic - * which fails in the workerd runtime. - * - * @param sourceFile the webpack runtime file parsed with ts-morph (note: this gets side-effectfully updated) - * @param chunkInstallationIdentifiers the names of the `installedChunks` and `installChunk` variables - * @param chunks the identifiers of the chunks (found on the filesystem) - * @returns the content of the sourceFile but with the require function updated - */ -export async function getFileContentWithUpdatedWebpackFRequireCode( - sourceFile: ts.SourceFile, - { installedChunks, installChunk }: { installedChunks: string; installChunk: string }, - chunks: string[] -): Promise { - const webpackFRequireFunction = sourceFile - .getDescendantsOfKind(ts.SyntaxKind.ArrowFunction) - .find((arrowFunction) => { - // the function is declared assigned in a binary expression, so let's check the binary expression - // to get more confidence that we've got the right arrow function - const binaryExpression = arrowFunction.getFirstAncestorByKind(ts.SyntaxKind.BinaryExpression); - if (!binaryExpression) return false; - - // the variable being assigned always ends with .f.require (even in unminified files) - const binaryExpressionLeft = binaryExpression.getLeft(); - if (!binaryExpressionLeft.getText().endsWith(".f.require")) return false; - - // the binary expression is an assignment - const binaryExpressionOperator = binaryExpression.getOperatorToken(); - if (binaryExpressionOperator.getText() !== "=") return false; - - // the right side of the expression is our arrow function - const binaryExpressionRight = binaryExpression.getRight(); - if (binaryExpressionRight !== arrowFunction) return false; - - const arrowFunctionBody = arrowFunction.getBody(); - if (!arrowFunctionBody.isKind(ts.SyntaxKind.Block)) return false; - - const arrowFunctionBodyText = arrowFunctionBody.getText(); - - const functionUsesChunkInstallationVariables = - arrowFunctionBodyText.includes(installChunk) && arrowFunctionBodyText.includes(installedChunks); - if (!functionUsesChunkInstallationVariables) return false; - - const functionParameters = arrowFunction.getParameters(); - if (functionParameters.length !== 2) return false; - - const callsInstallChunk = arrowFunctionBody - .getDescendantsOfKind(ts.SyntaxKind.CallExpression) - .some((callExpression) => callExpression.getExpression().getText() === installChunk); - if (!callsInstallChunk) return false; - - const functionFirstParameterName = functionParameters[0]?.getName(); - const accessesInstalledChunksUsingItsFirstParameter = arrowFunctionBody - .getDescendantsOfKind(ts.SyntaxKind.ElementAccessExpression) - .some((elementAccess) => { - return ( - elementAccess.getExpression().getText() === installedChunks && - elementAccess.getArgumentExpression()?.getText() === functionFirstParameterName - ); - }); - if (!accessesInstalledChunksUsingItsFirstParameter) return false; - - return true; - }); - - if (!webpackFRequireFunction) { - throw new Error("ERROR: unable to find the webpack f require function declaration"); - } - - const functionParameterNames = webpackFRequireFunction - .getParameters() - .map((parameter) => parameter.getName()); - const chunkId = functionParameterNames[0]; - - const functionBody = webpackFRequireFunction.getBody() as ts.Block; - - functionBody.replaceWithText(` -{ - if (${installedChunks}[${chunkId}]) { - return; - }${chunks - .map( - (chunk) => ` - if(${chunkId} === ${chunk}) { - return ${installChunk}(require("./chunks/${chunk}.js")); - }` - ) - .join("")} - throw new Error(\`Unknown chunk \${${chunkId}}\`); -}`); - - return sourceFile.print(); -} diff --git a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-updated-webpack-chunks-file-content.test.ts b/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-updated-webpack-chunks-file-content.test.ts deleted file mode 100644 index 673051cb..00000000 --- a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-updated-webpack-chunks-file-content.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { readFile } from "node:fs/promises"; - -import { describe, expect, test } from "vitest"; - -import { getUpdatedWebpackChunksFileContent } from "./get-updated-webpack-chunks-file-content.js"; - -describe("getUpdatedWebpackChunksFileContent", () => { - test("returns the updated content of a webpack runtime chunks unminified file", async () => { - const fileContent = await readFile( - `${import.meta.dirname}/test-fixtures/unminified-webpacks-file.js`, - "utf8" - ); - const updatedContent = await getUpdatedWebpackChunksFileContent(fileContent, ["658"]); - expect(updatedContent).toMatchFileSnapshot("./test-snapshots/unminified-webpacks-file.js"); - }); - - test("returns the updated content of a webpack runtime chunks minified file", async () => { - const fileContent = await readFile( - `${import.meta.dirname}/test-fixtures/minified-webpacks-file.js`, - "utf8" - ); - const updatedContent = await getUpdatedWebpackChunksFileContent(fileContent, ["658"]); - expect(updatedContent).toMatchFileSnapshot("./test-snapshots/minified-webpacks-file.js"); - }); -}); diff --git a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-updated-webpack-chunks-file-content.ts b/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-updated-webpack-chunks-file-content.ts deleted file mode 100644 index d4816573..00000000 --- a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/get-updated-webpack-chunks-file-content.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { tsParseFile } from "../../../utils/index.js"; -import { getChunkInstallationIdentifiers } from "./get-chunk-installation-identifiers.js"; -import { getFileContentWithUpdatedWebpackFRequireCode } from "./get-file-content-with-updated-webpack-f-require-code.js"; - -/** - * Updates the content of the webpack runtime file in a manner so that it doesn't perform runtime dynamic `require` calls which fail in our runtime. - * - * It does so by appropriately updating a function that in the unminified webpack runtime file appears as `__webpack_require__.f.require` which is - * the one that normally would cause dynamic requires to happen at runtime. - * - * `__webpack_require__.f.require` example: https://github.com/webpack/webpack/blob/dae16ad11e/examples/module-worker/README.md?plain=1#L284-L304 - * - * - * @param fileContent the content of the webpack runtime file - * @param chunks the identifiers of the chunks (found on the filesystem) - * @returns the content of the webpack runtime file updated with our custom logic - */ -export async function getUpdatedWebpackChunksFileContent( - fileContent: string, - chunks: string[] -): Promise { - const tsSourceFile = tsParseFile(fileContent); - - const chunkInstallationIdentifiers = await getChunkInstallationIdentifiers(tsSourceFile); - - const updatedFileContent = getFileContentWithUpdatedWebpackFRequireCode( - tsSourceFile, - chunkInstallationIdentifiers, - chunks - ); - - return updatedFileContent; -} diff --git a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/index.ts b/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/index.ts deleted file mode 100644 index e4e057d4..00000000 --- a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { readdirSync, readFileSync, writeFileSync } from "node:fs"; -import { join } from "node:path"; - -import { type BuildOptions, getPackagePath } from "@opennextjs/aws/build/helper.js"; - -import { getUpdatedWebpackChunksFileContent } from "./get-updated-webpack-chunks-file-content.js"; - -/** - * Fixes the webpack-runtime.js file by removing its webpack dynamic requires. - */ -export async function updateWebpackChunksFile(buildOpts: BuildOptions) { - console.log("# updateWebpackChunksFile"); - - const { outputDir } = buildOpts; - - const dotNextServerDir = join( - outputDir, - "server-functions/default", - getPackagePath(buildOpts), - ".next/server" - ); - - const webpackRuntimeFile = join(dotNextServerDir, "webpack-runtime.js"); - - const fileContent = readFileSync(webpackRuntimeFile, "utf-8"); - - const chunks = readdirSync(join(dotNextServerDir, "chunks")) - .filter((chunk) => /^\d+\.js$/.test(chunk)) - .map((chunk) => { - console.log(` - chunk ${chunk}`); - return chunk.replace(/\.js$/, ""); - }); - - const updatedFileContent = await getUpdatedWebpackChunksFileContent(fileContent, chunks); - - writeFileSync(webpackRuntimeFile, updatedFileContent); -} diff --git a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/test-fixtures/minified-webpacks-file.js b/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/test-fixtures/minified-webpacks-file.js deleted file mode 100644 index 5bf9fe4c..00000000 --- a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/test-fixtures/minified-webpacks-file.js +++ /dev/null @@ -1,89 +0,0 @@ -(() => { - "use strict"; - var e = {}, - r = {}; - function t(o) { - var n = r[o]; - if (void 0 !== n) return n.exports; - var a = (r[o] = { exports: {} }), - u = !0; - try { - e[o](a, a.exports, t), (u = !1); - } finally { - u && delete r[o]; - } - return a.exports; - } - (t.m = e), - (t.n = (e) => { - var r = e && e.__esModule ? () => e.default : () => e; - return t.d(r, { a: r }), r; - }), - (() => { - var e, - r = Object.getPrototypeOf - ? (e) => Object.getPrototypeOf(e) - : (e) => e.__proto__; - t.t = function (o, n) { - if ( - (1 & n && (o = this(o)), - 8 & n || - ("object" == typeof o && - o && - ((4 & n && o.__esModule) || - (16 & n && "function" == typeof o.then)))) - ) - return o; - var a = Object.create(null); - t.r(a); - var u = {}; - e = e || [null, r({}), r([]), r(r)]; - for ( - var f = 2 & n && o; - "object" == typeof f && !~e.indexOf(f); - f = r(f) - ) - Object.getOwnPropertyNames(f).forEach((e) => (u[e] = () => o[e])); - return (u.default = () => o), t.d(a, u), a; - }; - })(), - (t.d = (e, r) => { - for (var o in r) - t.o(r, o) && - !t.o(e, o) && - Object.defineProperty(e, o, { enumerable: !0, get: r[o] }); - }), - (t.f = {}), - (t.e = (e) => - Promise.all(Object.keys(t.f).reduce((r, o) => (t.f[o](e, r), r), []))), - (t.u = (e) => "" + e + ".js"), - (t.o = (e, r) => Object.prototype.hasOwnProperty.call(e, r)), - (t.r = (e) => { - "undefined" != typeof Symbol && - Symbol.toStringTag && - Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }), - Object.defineProperty(e, "__esModule", { value: !0 }); - }), - (t.X = (e, r, o) => { - var n = r; - o || ((r = e), (o = () => t((t.s = n)))), r.map(t.e, t); - var a = o(); - return void 0 === a ? e : a; - }), - (() => { - var e = { 658: 1 }, - r = (r) => { - var o = r.modules, - n = r.ids, - a = r.runtime; - for (var u in o) t.o(o, u) && (t.m[u] = o[u]); - a && a(t); - for (var f = 0; f < n.length; f++) e[n[f]] = 1; - }; - (t.f.require = (o, n) => { - e[o] || (658 != o ? r(require("./chunks/" + t.u(o))) : (e[o] = 1)); - }), - (module.exports = t), - (t.C = r); - })(); -})(); diff --git a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/test-fixtures/unminified-webpacks-file.js b/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/test-fixtures/unminified-webpacks-file.js deleted file mode 100644 index b6697be1..00000000 --- a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/test-fixtures/unminified-webpacks-file.js +++ /dev/null @@ -1,225 +0,0 @@ -/******/ (() => { // webpackBootstrap -/******/ "use strict"; -/******/ var __webpack_modules__ = ({}); -/************************************************************************/ -/******/ // The module cache -/******/ var __webpack_module_cache__ = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ // Check if module is in cache -/******/ var cachedModule = __webpack_module_cache__[moduleId]; -/******/ if (cachedModule !== undefined) { -/******/ return cachedModule.exports; - /******/ - } - /******/ // Create a new module (and put it into the cache) - /******/ var module = __webpack_module_cache__[moduleId] = { - /******/ // no module.id needed - /******/ // no module.loaded needed - /******/ exports: {} - /******/ - }; - /******/ - /******/ // Execute the module function - /******/ var threw = true; - /******/ try { - /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); - /******/ threw = false; - /******/ - } finally { - /******/ if (threw) delete __webpack_module_cache__[moduleId]; - /******/ - } - /******/ - /******/ // Return the exports of the module - /******/ return module.exports; - /******/ - } - /******/ - /******/ // expose the modules object (__webpack_modules__) - /******/ __webpack_require__.m = __webpack_modules__; - /******/ - /************************************************************************/ - /******/ /* webpack/runtime/compat get default export */ - /******/ (() => { - /******/ // getDefaultExport function for compatibility with non-harmony modules - /******/ __webpack_require__.n = (module) => { - /******/ var getter = module && module.__esModule ? - /******/ () => (module['default']) : - /******/ () => (module); - /******/ __webpack_require__.d(getter, { a: getter }); - /******/ return getter; - /******/ - }; - /******/ - })(); - /******/ - /******/ /* webpack/runtime/create fake namespace object */ - /******/ (() => { - /******/ var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__); - /******/ var leafPrototypes; - /******/ // create a fake namespace object - /******/ // mode & 1: value is a module id, require it - /******/ // mode & 2: merge all properties of value into the ns - /******/ // mode & 4: return value when already ns object - /******/ // mode & 16: return value when it's Promise-like - /******/ // mode & 8|1: behave like require - /******/ __webpack_require__.t = function (value, mode) { - /******/ if (mode & 1) value = this(value); - /******/ if (mode & 8) return value; - /******/ if (typeof value === 'object' && value) { - /******/ if ((mode & 4) && value.__esModule) return value; - /******/ if ((mode & 16) && typeof value.then === 'function') return value; - /******/ - } - /******/ var ns = Object.create(null); - /******/ __webpack_require__.r(ns); - /******/ var def = {}; - /******/ leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)]; - /******/ for (var current = mode & 2 && value; typeof current == 'object' && !~leafPrototypes.indexOf(current); current = getProto(current)) { - /******/ Object.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key]))); - /******/ - } - /******/ def['default'] = () => (value); - /******/ __webpack_require__.d(ns, def); - /******/ return ns; - /******/ - }; - /******/ - })(); - /******/ - /******/ /* webpack/runtime/define property getters */ - /******/ (() => { - /******/ // define getter functions for harmony exports - /******/ __webpack_require__.d = (exports, definition) => { - /******/ for (var key in definition) { - /******/ if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { - /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); - /******/ - } - /******/ - } - /******/ - }; - /******/ - })(); - /******/ - /******/ /* webpack/runtime/ensure chunk */ - /******/ (() => { - /******/ __webpack_require__.f = {}; - /******/ // This file contains only the entry chunk. - /******/ // The chunk loading function for additional chunks - /******/ __webpack_require__.e = (chunkId) => { - /******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => { - /******/ __webpack_require__.f[key](chunkId, promises); - /******/ return promises; - /******/ - }, [])); - /******/ - }; - /******/ - })(); - /******/ - /******/ /* webpack/runtime/get javascript chunk filename */ - /******/ (() => { - /******/ // This function allow to reference async chunks and sibling chunks for the entrypoint - /******/ __webpack_require__.u = (chunkId) => { - /******/ // return url for filenames based on template - /******/ return "" + chunkId + ".js"; - /******/ - }; - /******/ - })(); - /******/ - /******/ /* webpack/runtime/hasOwnProperty shorthand */ - /******/ (() => { - /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) - /******/ - })(); - /******/ - /******/ /* webpack/runtime/make namespace object */ - /******/ (() => { - /******/ // define __esModule on exports - /******/ __webpack_require__.r = (exports) => { - /******/ if (typeof Symbol !== 'undefined' && Symbol.toStringTag) { - /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); - /******/ - } - /******/ Object.defineProperty(exports, '__esModule', { value: true }); - /******/ - }; - /******/ - })(); - /******/ - /******/ /* webpack/runtime/startup entrypoint */ - /******/ (() => { - /******/ __webpack_require__.X = (result, chunkIds, fn) => { - /******/ // arguments: chunkIds, moduleId are deprecated - /******/ var moduleId = chunkIds; - /******/ if (!fn) chunkIds = result, fn = () => (__webpack_require__(__webpack_require__.s = moduleId)); - /******/ chunkIds.map(__webpack_require__.e, __webpack_require__) - /******/ var r = fn(); - /******/ return r === undefined ? result : r; - /******/ - } - /******/ - })(); - /******/ - /******/ /* webpack/runtime/require chunk loading */ - /******/ (() => { - /******/ // no baseURI - /******/ - /******/ // object to store loaded chunks - /******/ // "1" means "loaded", otherwise not loaded yet - /******/ var installedChunks = { - /******/ 658: 1 - /******/ - }; - /******/ - /******/ // no on chunks loaded - /******/ - /******/ var installChunk = (chunk) => { - /******/ var moreModules = chunk.modules, chunkIds = chunk.ids, runtime = chunk.runtime; - /******/ for (var moduleId in moreModules) { - /******/ if (__webpack_require__.o(moreModules, moduleId)) { - /******/ __webpack_require__.m[moduleId] = moreModules[moduleId]; - /******/ - } - /******/ - } - /******/ if (runtime) runtime(__webpack_require__); - /******/ for (var i = 0; i < chunkIds.length; i++) - /******/ installedChunks[chunkIds[i]] = 1; - /******/ - /******/ - }; - /******/ - /******/ // require() chunk loading for javascript - /******/ __webpack_require__.f.require = (chunkId, promises) => { - /******/ // "1" is the signal for "already loaded" - /******/ if (!installedChunks[chunkId]) { - /******/ if (658 != chunkId) { - /******/ installChunk(require("./chunks/" + __webpack_require__.u(chunkId))); - /******/ - } else installedChunks[chunkId] = 1; - /******/ - } - /******/ - }; - /******/ - /******/ module.exports = __webpack_require__; - /******/ __webpack_require__.C = installChunk; - /******/ - /******/ // no HMR - /******/ - /******/ // no HMR manifest - /******/ - })(); - /******/ - /************************************************************************/ - /******/ - /******/ - /******/ -})() - ; \ No newline at end of file diff --git a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/test-snapshots/minified-webpacks-file.js b/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/test-snapshots/minified-webpacks-file.js deleted file mode 100644 index 184e706a..00000000 --- a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/test-snapshots/minified-webpacks-file.js +++ /dev/null @@ -1,86 +0,0 @@ -(() => { - "use strict"; - var e = {}, r = {}; - function t(o) { - var n = r[o]; - if (void 0 !== n) - return n.exports; - var a = (r[o] = { exports: {} }), u = !0; - try { - e[o](a, a.exports, t), (u = !1); - } - finally { - u && delete r[o]; - } - return a.exports; - } - (t.m = e), - (t.n = (e) => { - var r = e && e.__esModule ? () => e.default : () => e; - return t.d(r, { a: r }), r; - }), - (() => { - var e, r = Object.getPrototypeOf - ? (e) => Object.getPrototypeOf(e) - : (e) => e.__proto__; - t.t = function (o, n) { - if ((1 & n && (o = this(o)), - 8 & n || - ("object" == typeof o && - o && - ((4 & n && o.__esModule) || - (16 & n && "function" == typeof o.then))))) - return o; - var a = Object.create(null); - t.r(a); - var u = {}; - e = e || [null, r({}), r([]), r(r)]; - for (var f = 2 & n && o; "object" == typeof f && !~e.indexOf(f); f = r(f)) - Object.getOwnPropertyNames(f).forEach((e) => (u[e] = () => o[e])); - return (u.default = () => o), t.d(a, u), a; - }; - })(), - (t.d = (e, r) => { - for (var o in r) - t.o(r, o) && - !t.o(e, o) && - Object.defineProperty(e, o, { enumerable: !0, get: r[o] }); - }), - (t.f = {}), - (t.e = (e) => Promise.all(Object.keys(t.f).reduce((r, o) => (t.f[o](e, r), r), []))), - (t.u = (e) => "" + e + ".js"), - (t.o = (e, r) => Object.prototype.hasOwnProperty.call(e, r)), - (t.r = (e) => { - "undefined" != typeof Symbol && - Symbol.toStringTag && - Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }), - Object.defineProperty(e, "__esModule", { value: !0 }); - }), - (t.X = (e, r, o) => { - var n = r; - o || ((r = e), (o = () => t((t.s = n)))), r.map(t.e, t); - var a = o(); - return void 0 === a ? e : a; - }), - (() => { - var e = { 658: 1 }, r = (r) => { - var o = r.modules, n = r.ids, a = r.runtime; - for (var u in o) - t.o(o, u) && (t.m[u] = o[u]); - a && a(t); - for (var f = 0; f < n.length; f++) - e[n[f]] = 1; - }; - (t.f.require = (o, n) => { - if (e[o]) { - return; - } - if (o === 658) { - return r(require("./chunks/658.js")); - } - throw new Error(`Unknown chunk ${o}`); - }), - (module.exports = t), - (t.C = r); - })(); -})(); diff --git a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/test-snapshots/unminified-webpacks-file.js b/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/test-snapshots/unminified-webpacks-file.js deleted file mode 100644 index 449727d2..00000000 --- a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/test-snapshots/unminified-webpacks-file.js +++ /dev/null @@ -1,230 +0,0 @@ -/******/ (() => { - /******/ "use strict"; - /******/ var __webpack_modules__ = ({}); - /************************************************************************/ - /******/ // The module cache - /******/ var __webpack_module_cache__ = {}; - /******/ - /******/ // The require function - /******/ function __webpack_require__(moduleId) { - /******/ // Check if module is in cache - /******/ var cachedModule = __webpack_module_cache__[moduleId]; - /******/ if (cachedModule !== undefined) { - /******/ return cachedModule.exports; - /******/ - } - /******/ // Create a new module (and put it into the cache) - /******/ var module = __webpack_module_cache__[moduleId] = { - /******/ // no module.id needed - /******/ // no module.loaded needed - /******/ exports: {} - /******/ - }; - /******/ - /******/ // Execute the module function - /******/ var threw = true; - /******/ try { - /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); - /******/ threw = false; - /******/ - } - finally { - /******/ if (threw) - delete __webpack_module_cache__[moduleId]; - /******/ - } - /******/ - /******/ // Return the exports of the module - /******/ return module.exports; - /******/ - } - /******/ - /******/ // expose the modules object (__webpack_modules__) - /******/ __webpack_require__.m = __webpack_modules__; - /******/ - /************************************************************************/ - /******/ /* webpack/runtime/compat get default export */ - /******/ (() => { - /******/ // getDefaultExport function for compatibility with non-harmony modules - /******/ __webpack_require__.n = (module) => { - /******/ var getter = module && module.__esModule ? - /******/ () => (module['default']) : - /******/ () => (module); - /******/ __webpack_require__.d(getter, { a: getter }); - /******/ return getter; - /******/ - }; - /******/ - })(); - /******/ - /******/ /* webpack/runtime/create fake namespace object */ - /******/ (() => { - /******/ var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__); - /******/ var leafPrototypes; - /******/ // create a fake namespace object - /******/ // mode & 1: value is a module id, require it - /******/ // mode & 2: merge all properties of value into the ns - /******/ // mode & 4: return value when already ns object - /******/ // mode & 16: return value when it's Promise-like - /******/ // mode & 8|1: behave like require - /******/ __webpack_require__.t = function (value, mode) { - /******/ if (mode & 1) - value = this(value); - /******/ if (mode & 8) - return value; - /******/ if (typeof value === 'object' && value) { - /******/ if ((mode & 4) && value.__esModule) - return value; - /******/ if ((mode & 16) && typeof value.then === 'function') - return value; - /******/ - } - /******/ var ns = Object.create(null); - /******/ __webpack_require__.r(ns); - /******/ var def = {}; - /******/ leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)]; - /******/ for (var current = mode & 2 && value; typeof current == 'object' && !~leafPrototypes.indexOf(current); current = getProto(current)) { - /******/ Object.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key]))); - /******/ - } - /******/ def['default'] = () => (value); - /******/ __webpack_require__.d(ns, def); - /******/ return ns; - /******/ - }; - /******/ - })(); - /******/ - /******/ /* webpack/runtime/define property getters */ - /******/ (() => { - /******/ // define getter functions for harmony exports - /******/ __webpack_require__.d = (exports, definition) => { - /******/ for (var key in definition) { - /******/ if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { - /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); - /******/ - } - /******/ - } - /******/ - }; - /******/ - })(); - /******/ - /******/ /* webpack/runtime/ensure chunk */ - /******/ (() => { - /******/ __webpack_require__.f = {}; - /******/ // This file contains only the entry chunk. - /******/ // The chunk loading function for additional chunks - /******/ __webpack_require__.e = (chunkId) => { - /******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => { - /******/ __webpack_require__.f[key](chunkId, promises); - /******/ return promises; - /******/ - }, [])); - /******/ - }; - /******/ - })(); - /******/ - /******/ /* webpack/runtime/get javascript chunk filename */ - /******/ (() => { - /******/ // This function allow to reference async chunks and sibling chunks for the entrypoint - /******/ __webpack_require__.u = (chunkId) => { - /******/ // return url for filenames based on template - /******/ return "" + chunkId + ".js"; - /******/ - }; - /******/ - })(); - /******/ - /******/ /* webpack/runtime/hasOwnProperty shorthand */ - /******/ (() => { - /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)); - /******/ - })(); - /******/ - /******/ /* webpack/runtime/make namespace object */ - /******/ (() => { - /******/ // define __esModule on exports - /******/ __webpack_require__.r = (exports) => { - /******/ if (typeof Symbol !== 'undefined' && Symbol.toStringTag) { - /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); - /******/ - } - /******/ Object.defineProperty(exports, '__esModule', { value: true }); - /******/ - }; - /******/ - })(); - /******/ - /******/ /* webpack/runtime/startup entrypoint */ - /******/ (() => { - /******/ __webpack_require__.X = (result, chunkIds, fn) => { - /******/ // arguments: chunkIds, moduleId are deprecated - /******/ var moduleId = chunkIds; - /******/ if (!fn) - chunkIds = result, fn = () => (__webpack_require__(__webpack_require__.s = moduleId)); - /******/ chunkIds.map(__webpack_require__.e, __webpack_require__); - /******/ var r = fn(); - /******/ return r === undefined ? result : r; - /******/ - }; - /******/ - })(); - /******/ - /******/ /* webpack/runtime/require chunk loading */ - /******/ (() => { - /******/ // no baseURI - /******/ - /******/ // object to store loaded chunks - /******/ // "1" means "loaded", otherwise not loaded yet - /******/ var installedChunks = { - /******/ 658: 1 - /******/ - }; - /******/ - /******/ // no on chunks loaded - /******/ - /******/ var installChunk = (chunk) => { - /******/ var moreModules = chunk.modules, chunkIds = chunk.ids, runtime = chunk.runtime; - /******/ for (var moduleId in moreModules) { - /******/ if (__webpack_require__.o(moreModules, moduleId)) { - /******/ __webpack_require__.m[moduleId] = moreModules[moduleId]; - /******/ - } - /******/ - } - /******/ if (runtime) - runtime(__webpack_require__); - /******/ for (var i = 0; i < chunkIds.length; i++) - /******/ installedChunks[chunkIds[i]] = 1; - /******/ - /******/ - }; - /******/ - /******/ // require() chunk loading for javascript - /******/ __webpack_require__.f.require = (chunkId, promises) => { - if (installedChunks[chunkId]) { - return; - } - if (chunkId === 658) { - return installChunk(require("./chunks/658.js")); - } - throw new Error(`Unknown chunk ${chunkId}`); - }; - /******/ - /******/ module.exports = __webpack_require__; - /******/ __webpack_require__.C = installChunk; - /******/ - /******/ // no HMR - /******/ - /******/ // no HMR manifest - /******/ - })(); - /******/ - /************************************************************************/ - /******/ - /******/ - /******/ -})();