Skip to content

community-cli-plugin: Refactor CLI build command to use Metro.runBuild #51124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
80 changes: 33 additions & 47 deletions packages/community-cli-plugin/src/commands/bundle/buildBundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,15 @@
*/

import type {Config} from '@react-native-community/cli-types';
import type {RunBuildOptions} from 'metro';
import type {ConfigT} from 'metro-config';
import type {RequestOptions} from 'metro/src/shared/types.flow';

import loadMetroConfig from '../../utils/loadMetroConfig';
import parseKeyValueParamArray from '../../utils/parseKeyValueParamArray';
import saveAssets from './saveAssets';
import chalk from 'chalk';
import {promises as fs} from 'fs';
import Server from 'metro/src/Server';
import metroBundle from 'metro/src/shared/output/bundle';
import metroRamBundle from 'metro/src/shared/output/RamBundle';
import {runBuild} from 'metro';
import path from 'path';

export type BundleCommandArgs = {
Expand All @@ -41,7 +39,7 @@ export type BundleCommandArgs = {
sourcemapSourcesRoot?: string,
sourcemapUseAbsolutePath: boolean,
verbose: boolean,
unstableTransformProfile: string,
unstableTransformProfile: 'hermes-stable' | 'hermes-canary' | 'default',
indexedRamBundle?: boolean,
resolverOption?: Array<string>,
};
Expand All @@ -50,7 +48,7 @@ async function buildBundle(
_argv: Array<string>,
ctx: Config,
args: BundleCommandArgs,
bundleImpl: typeof metroBundle | typeof metroRamBundle = metroBundle,
bundleImpl?: RunBuildOptions['output'],
): Promise<void> {
const config = await loadMetroConfig(ctx, {
maxWorkers: args.maxWorkers,
Expand All @@ -64,7 +62,7 @@ async function buildBundle(
async function buildBundleWithConfig(
args: BundleCommandArgs,
config: ConfigT,
bundleImpl: typeof metroBundle | typeof metroRamBundle = metroBundle,
bundleImpl?: RunBuildOptions['output'],
): Promise<void> {
const customResolverOptions = parseKeyValueParamArray(
args.resolverOption ?? [],
Expand Down Expand Up @@ -97,52 +95,40 @@ async function buildBundleWithConfig(
sourceMapUrl = path.basename(sourceMapUrl);
}

// $FlowIgnore[prop-missing]
const requestOpts: RequestOptions & {...} = {
entryFile: args.entryFile,
sourceMapUrl,
const runBuildOptions: RunBuildOptions = {
assets: true,
customResolverOptions,
dev: args.dev,
entry: args.entryFile,
minify: args.minify !== undefined ? args.minify : !args.dev,
output: bundleImpl,
platform: args.platform,
// $FlowFixMe[incompatible-type] Remove suppression after Metro 0.82.3
sourceMapUrl,
unstable_transformProfile: args.unstableTransformProfile,
customResolverOptions,
};
const server = new Server(config);

try {
const bundle = await bundleImpl.build(server, requestOpts);

// Ensure destination directory exists before saving the bundle
await fs.mkdir(path.dirname(args.bundleOutput), {
recursive: true,
mode: 0o755,
});

// $FlowIgnore[class-object-subtyping]
// $FlowIgnore[incompatible-call]
// $FlowIgnore[prop-missing]
// $FlowIgnore[incompatible-exact]
await bundleImpl.save(bundle, args, console.info);

// Save the assets of the bundle
// $FlowFixMe[prop-missing] Remove suppression after Metro 0.82.3
const outputAssets = await server.getAssets({
...Server.DEFAULT_BUNDLE_OPTIONS,
...requestOpts,
bundleType: 'todo',
});

// When we're done saving bundle output and the assets, we're done.
return await saveAssets(
outputAssets,
args.platform,
args.assetsDest,
args.assetCatalogDest,
);
} finally {
await server.end();

// Ensure destination directory exists before running the build
await fs.mkdir(path.dirname(args.bundleOutput), {
recursive: true,
mode: 0o755,
});

const result = await runBuild(config, runBuildOptions);

// Save the assets of the bundle
if (result.assets == null) {
throw new Error("Assets missing from Metro's runBuild result");
}

const outputAssets = result.assets;

// When we're done saving bundle output and the assets, we're done.
await saveAssets(
outputAssets,
args.platform,
args.assetsDest,
args.assetCatalogDest,
);
}

/**
Expand Down
Loading