Skip to content
Open
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
11 changes: 11 additions & 0 deletions .changeset/weak-crews-tickle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@opennextjs/cloudflare": minor
---

Support multiple Wrangler configuration files via `--config` flag

Enable passing multiple configuration files to the OpenNext.js Cloudflare CLI
using the `--config` flag, matching Wrangler's native capability. This allows
running multiple workers in a single dev session, which is essential for RPC
communication with Durable Objects during local development as documented in the
[Wrangler API bindings guide](https://developers.cloudflare.com/workers/wrangler/api/#supported-bindings)
4 changes: 2 additions & 2 deletions packages/cloudflare/src/cli/commands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export async function deployCommand(args: WithWranglerArgs<{ cacheChunkSize: num
const wranglerConfig = readWranglerConfig(args);

const envVars = await getEnvFromPlatformProxy({
configPath: args.wranglerConfigPath,
configPath: args.nextjsWranglerConfigPath,
environment: args.env,
});

Expand All @@ -37,7 +37,7 @@ export async function deployCommand(args: WithWranglerArgs<{ cacheChunkSize: num
await populateCache(options, config, wranglerConfig, {
target: "remote",
environment: args.env,
wranglerConfigPath: args.wranglerConfigPath,
wranglerConfigPath: args.nextjsWranglerConfigPath,
cacheChunkSize: args.cacheChunkSize,
});

Expand Down
2 changes: 1 addition & 1 deletion packages/cloudflare/src/cli/commands/populate-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ async function populateCacheCommand(
await populateCache(options, config, wranglerConfig, {
target,
environment: args.env,
wranglerConfigPath: args.wranglerConfigPath,
wranglerConfigPath: args.nextjsWranglerConfigPath,
cacheChunkSize: args.cacheChunkSize,
});
}
Expand Down
2 changes: 1 addition & 1 deletion packages/cloudflare/src/cli/commands/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export async function previewCommand(args: WithWranglerArgs<{ cacheChunkSize: nu
await populateCache(options, config, wranglerConfig, {
target: "local",
environment: args.env,
wranglerConfigPath: args.wranglerConfigPath,
wranglerConfigPath: args.nextjsWranglerConfigPath,
cacheChunkSize: args.cacheChunkSize,
});

Expand Down
4 changes: 2 additions & 2 deletions packages/cloudflare/src/cli/commands/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export async function uploadCommand(args: WithWranglerArgs<{ cacheChunkSize: num
const wranglerConfig = readWranglerConfig(args);

const envVars = await getEnvFromPlatformProxy({
configPath: args.wranglerConfigPath,
configPath: args.nextjsWranglerConfigPath,
environment: args.env,
});

Expand All @@ -37,7 +37,7 @@ export async function uploadCommand(args: WithWranglerArgs<{ cacheChunkSize: num
await populateCache(options, config, wranglerConfig, {
target: "remote",
environment: args.env,
wranglerConfigPath: args.wranglerConfigPath,
wranglerConfigPath: args.nextjsWranglerConfigPath,
cacheChunkSize: args.cacheChunkSize,
});

Expand Down
21 changes: 15 additions & 6 deletions packages/cloudflare/src/cli/commands/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import { createOpenNextConfigIfNotExistent, ensureCloudflareConfig } from "../bu
export type WithWranglerArgs<T = unknown> = T & {
// Array of arguments that can be given to wrangler commands, including the `--config` and `--env` args.
wranglerArgs: string[];
wranglerConfigPath: string | undefined;
wranglerConfigPath: string[] | undefined;
// The first wrangler config path passed into the CLI, if any. Assumed to be the one used for OpenNext.
nextjsWranglerConfigPath: string | undefined;
env: string | undefined;
};

Expand Down Expand Up @@ -101,7 +103,7 @@ export function getNormalizedOptions(config: OpenNextConfig, buildDir = nextAppD
* @returns Wrangler config.
*/
export function readWranglerConfig(args: WithWranglerArgs) {
return unstable_readConfig({ env: args.env, config: args.wranglerConfigPath });
return unstable_readConfig({ env: args.env, config: args.nextjsWranglerConfigPath });
}

/**
Expand All @@ -111,6 +113,7 @@ export function withWranglerOptions<T extends yargs.Argv>(args: T) {
return args
.option("config", {
type: "string",
array: true,
alias: "c",
desc: "Path to Wrangler configuration file",
})
Expand All @@ -128,7 +131,7 @@ export function withWranglerOptions<T extends yargs.Argv>(args: T) {

type WranglerInputArgs = {
configPath: string | undefined;
config: string | undefined;
config: string[] | undefined;
env: string | undefined;
};

Expand All @@ -143,15 +146,15 @@ function getWranglerArgs(args: WranglerInputArgs & { _: (string | number)[] }):

if (args.config) {
logger.error(
"Multiple config flags found. Please use the `--config` flag for your Wrangler config path."
"Duplicate config flags found. Unable to pass both `--config` and `--configPath`. Please use the `--config` flag for your Wrangler config path."
);
process.exit(1);
}
}

return [
...(args.configPath ? ["--config", args.configPath] : []),
...(args.config ? ["--config", args.config] : []),
...(args.config ? args.config.flatMap((c) => ["--config", c]) : []),
...(args.env ? ["--env", args.env] : []),
// Note: the first args in `_` will be the commands.
...args._.slice(args._[0] === "populateCache" ? 2 : 1).map((a) => `${a}`),
Expand All @@ -166,9 +169,15 @@ function getWranglerArgs(args: WranglerInputArgs & { _: (string | number)[] }):
export function withWranglerPassthroughArgs<T extends yargs.ArgumentsCamelCase<WranglerInputArgs>>(
args: T
): WithWranglerArgs<T> {
const wranglerConfigPath = args.config ?? (args.configPath ? [args.configPath] : undefined);
if (wranglerConfigPath && wranglerConfigPath.length > 1) {
logger.info("Multiple Wrangler config paths found, first config assumed as opennext config.");
}

return {
...args,
wranglerConfigPath: args.config ?? args.configPath,
wranglerConfigPath,
nextjsWranglerConfigPath: wranglerConfigPath?.[0],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly this will only work when the next app config is first which is not ideal.

Can't you run opennextjs-cloudflare ... (for the next app) and wrangler dev ... for other workers?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this isn't ideal but I couldn't think of another solution.

You can run them in separate dev sessions but you'll hit them limitation outline in the documentation;

If you are not using RPC with your Durable Object, you can run a separate Wrangler dev session alongside your framework development server.
Otherwise, you can build your application and run both Workers in the same Wrangler dev session.

I found this when trying to port the agents starter to opennext-cloudflare which is working when I link this change.

I'm trying to run them locally in separate dev sessions now but its having an issue upgrading to web-sockets I've not debugged yet.

I'm open to other ways of solving this or I can just open an issue so it can be fixed upstream in wrangler somehow

wranglerArgs: getWranglerArgs(args),
};
}