Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions packages/cloudflare/src/api/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,21 @@ import type {
Queue,
TagCache,
} from "@opennextjs/aws/types/overrides.js";
import type { BuildOptions as EsbuildBuildOptions } from "esbuild";

import assetResolver from "./overrides/asset-resolver/index.js";

export type Override<T extends BaseOverride> = "dummy" | T | LazyLoadedOverride<T>;
export type EsbuildOverride =
| Partial<EsbuildBuildOptions>
| ((options: EsbuildBuildOptions) => EsbuildBuildOptions);

export type CloudflareEsbuildOverrides = {
/**
* Allows customizing the esbuild configuration used when bundling the worker server.
*/
bundleServer?: EsbuildOverride;
};

/**
* Cloudflare specific overrides.
Expand Down Expand Up @@ -55,6 +66,11 @@ export type CloudflareOverrides = {
* @default "none"
*/
routePreloadingBehavior?: RoutePreloadingBehavior;

/**
* Low-level overrides for the esbuild invocations performed by the Cloudflare adapter.
*/
esbuild?: CloudflareEsbuildOverrides;
};

/**
Expand All @@ -71,6 +87,7 @@ export function defineCloudflareConfig(config: CloudflareOverrides = {}): OpenNe
cachePurge,
enableCacheInterception = false,
routePreloadingBehavior = "none",
esbuild: esbuildOverrides,
} = config;

return {
Expand All @@ -90,6 +107,7 @@ export function defineCloudflareConfig(config: CloudflareOverrides = {}): OpenNe
edgeExternals: ["node:crypto"],
cloudflare: {
useWorkerdCondition: true,
...(esbuildOverrides ? { esbuild: esbuildOverrides } : {}),
},
dangerous: {
enableCacheInterception,
Expand Down Expand Up @@ -179,6 +197,11 @@ interface OpenNextConfig extends AwsOpenNextConfig {
// @default 7
maxVersionAgeDays?: number;
};

/**
* Low-level overrides for the esbuild invocations performed by the Cloudflare adapter.
*/
esbuild?: CloudflareEsbuildOverrides;
};
}

Expand Down
44 changes: 40 additions & 4 deletions packages/cloudflare/src/cli/build/bundle-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import { fileURLToPath } from "node:url";

import { type BuildOptions, getPackagePath } from "@opennextjs/aws/build/helper.js";
import { ContentUpdater } from "@opennextjs/aws/plugins/content-updater.js";
import { build, type Plugin } from "esbuild";
import { build, type BuildOptions as EsbuildBuildOptions, type Plugin } from "esbuild";

import type { EsbuildOverride } from "../../api/config.js";
import { getOpenNextConfig } from "../../api/config.js";
import type { ProjectOptions } from "../project-options.js";
import { patchVercelOgLibrary } from "./patches/ast/patch-vercel-og-library.js";
Expand Down Expand Up @@ -50,6 +51,7 @@ export async function bundleServer(buildOpts: BuildOptions, projectOpts: Project
copyPackageCliFiles(packageDistDir, buildOpts);

const { appPath, outputDir, monorepoRoot, debug } = buildOpts;
const cloudflareConfig = getOpenNextConfig(buildOpts).cloudflare;
const baseManifestPath = path.join(
outputDir,
"server-functions/default",
Expand All @@ -71,7 +73,7 @@ export async function bundleServer(buildOpts: BuildOptions, projectOpts: Project

const updater = new ContentUpdater(buildOpts);

const result = await build({
const baseEsbuildOptions: EsbuildBuildOptions = {
entryPoints: [openNextServer],
bundle: true,
outfile: openNextServerBundle,
Expand All @@ -92,7 +94,7 @@ export async function bundleServer(buildOpts: BuildOptions, projectOpts: Project
// - default nft conditions: https://github.com/vercel/nft/blob/2b55b01/readme.md#exports--imports
// - Next no explicit override: https://github.com/vercel/next.js/blob/2efcf11/packages/next/src/build/collect-build-traces.ts#L287
// - ESBuild `node` platform: https://esbuild.github.io/api/#platform
conditions: getOpenNextConfig(buildOpts).cloudflare?.useWorkerdCondition === false ? [] : ["workerd"],
conditions: cloudflareConfig?.useWorkerdCondition === false ? [] : ["workerd"],
plugins: [
shimRequireHook(buildOpts),
inlineDynamicRequires(updater, buildOpts),
Expand Down Expand Up @@ -159,7 +161,14 @@ export async function bundleServer(buildOpts: BuildOptions, projectOpts: Project
js: `import {setInterval, clearInterval, setTimeout, clearTimeout, setImmediate, clearImmediate} from "node:timers"`,
},
platform: "node",
});
};

const resolvedEsbuildOptions = applyEsbuildOverride(
baseEsbuildOptions,
cloudflareConfig?.esbuild?.bundleServer
);

const result = await build(resolvedEsbuildOptions);

fs.writeFileSync(openNextServerBundle + ".meta.json", JSON.stringify(result.metafile, null, 2));

Expand Down Expand Up @@ -187,6 +196,33 @@ export async function updateWorkerBundledCode(workerOutputFile: string): Promise
await writeFile(workerOutputFile, patchedCode);
}

function applyEsbuildOverride(
baseOptions: EsbuildBuildOptions,
override: EsbuildOverride | undefined
): EsbuildBuildOptions {
if (!override) {
return baseOptions;
}

if (typeof override === "function") {
return override(baseOptions);
}

const merged: EsbuildBuildOptions = {
...baseOptions,
...override,
};

if (override.logOverride || baseOptions.logOverride) {
merged.logOverride = {
...baseOptions.logOverride,
...override.logOverride,
};
}

return merged;
}

/**
* Gets the path of the worker.js file generated by the build process
*
Expand Down