Remove commander dependency from main package (#57645)

Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57645

Simplify the `scripts/bundle.js` wrapper and remove the `commander` dependency from `packages/react-native`.

This script is a lightweight wrapper around `npx react-native bundle`, with extra local config arg handling (for now, unchanged / remains located here).

**Refactor only** with script behaviour unchanged.

**Other changes**

- Combined arg parsing is hoisted into `community-cli-plugin` (which does have `commander`) via `unstable_createBundleCommandParser`.
- Drop `program` value export (also unused).

**Notes**

After this change, only `yargs` remains as a direct dependency `react-native` package (`packages/react-native/scripts/`) (a future cleanup).

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D113389458

fbshipit-source-id: 09dbde6f86260bc8abdb8cb82ce1503ac6139952
This commit is contained in:
Alex Hunt
2026-07-23 17:07:02 -07:00
committed by meta-codesync[bot]
parent 3be254a8af
commit 02315146f2
5 changed files with 119 additions and 55 deletions
@@ -33,6 +33,7 @@
"dependencies": {
"@react-native/asset-utils": "0.87.0-main",
"@react-native/dev-middleware": "0.87.0-main",
"commander": "^12.0.0",
"debug": "^4.4.0",
"invariant": "^2.2.4",
"metro": "^0.87.0",
@@ -8,14 +8,22 @@
* @format
*/
import type {Command} from '@react-native-community/cli-types';
import type {Command as CommunityCommand} from '@react-native-community/cli-types';
import buildBundle from './buildBundle';
import {Command} from 'commander';
import path from 'node:path';
export type {BundleCommandArgs} from './buildBundle';
const bundleCommand: Command = {
type CommandOption = Readonly<NonNullable<CommunityCommand['options']>[number]>;
type BundleCommandParser = {
parser: Command,
baseHelpInformation: string,
};
const bundleCommand: CommunityCommand = {
name: 'bundle',
description: 'Build the bundle for the provided JavaScript entry file.',
func: buildBundle,
@@ -123,4 +131,43 @@ const bundleCommand: Command = {
],
};
function addOptions(
command: Command,
options: ReadonlyArray<CommandOption>,
): void {
for (const option of options) {
const description = option.description ?? '';
const defaultValue =
typeof option.default === 'function' ? undefined : option.default;
if (option.parse != null) {
command.option(option.name, description, option.parse, defaultValue);
} else if (
typeof defaultValue === 'string' ||
typeof defaultValue === 'boolean' ||
Array.isArray(defaultValue)
) {
command.option(option.name, description, defaultValue);
} else {
command.option(option.name, description);
}
}
}
export function unstable_createBundleCommandParser(
additionalOptions: ReadonlyArray<CommandOption> = [],
): BundleCommandParser {
const parser = new Command()
.name(bundleCommand.name)
.description(bundleCommand.description ?? '')
.helpOption('--help', 'Display help for command')
.allowUnknownOption();
addOptions(parser, bundleCommand.options ?? []);
const baseHelpInformation = parser.helpInformation();
addOptions(parser, additionalOptions);
return {parser, baseHelpInformation};
}
export default bundleCommand;
@@ -8,7 +8,10 @@
* @format
*/
export {default as bundleCommand} from './commands/bundle';
export {
default as bundleCommand,
unstable_createBundleCommandParser,
} from './commands/bundle';
export {default as startCommand} from './commands/start';
export {unstable_buildBundleWithConfig} from './commands/bundle/buildBundle';