Skip to content

Commit e7c2aeb

Browse files
feat: add invoking CLI's scripts for launching Metro in run-ios command (#2021)
* feat: sync starting bundler implementations * fix: remove starting packager from build-* commands * feat: add better request response handling * fix: add missing options * chore: remove usage of `cli-plugin-metro` package by exposing command * fix: remove useless dependencies * feat: merge starting bundler hooks to `start` command & add interactivity * fix: adjust descriptions * chore: code review improvements * fix: move logic to `run-ios/android` commands * fix: move scripts to correct directory * chore: simplify naming * chore: code cleaning * chore: lockfile * fix: remove unnecessary dependency * chore: unify `handlePortUnavailable`
1 parent f8db7b2 commit e7c2aeb

File tree

25 files changed

+593
-294
lines changed

25 files changed

+593
-294
lines changed

packages/cli-clean/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"@react-native-community/cli-tools": "12.0.0-alpha.8",
1212
"chalk": "^4.1.2",
1313
"execa": "^5.0.0",
14-
"prompts": "^2.4.0"
14+
"prompts": "^2.4.2"
1515
},
1616
"files": [
1717
"build",
@@ -20,7 +20,7 @@
2020
],
2121
"devDependencies": {
2222
"@react-native-community/cli-types": "12.0.0-alpha.8",
23-
"@types/prompts": "^2.0.9"
23+
"@types/prompts": "^2.4.4"
2424
},
2525
"homepage": "https://github.com/react-native-community/cli/tree/main/packages/cli-clean",
2626
"repository": {

packages/cli-doctor/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
"@react-native-community/cli-config": "12.0.0-alpha.8",
1212
"@react-native-community/cli-platform-android": "12.0.0-alpha.8",
1313
"@react-native-community/cli-platform-ios": "12.0.0-alpha.8",
14-
"@react-native-community/cli-plugin-metro": "12.0.0-alpha.8",
1514
"@react-native-community/cli-tools": "12.0.0-alpha.8",
1615
"chalk": "^4.1.2",
1716
"command-exists": "^1.2.8",
@@ -21,7 +20,7 @@
2120
"ip": "^1.1.5",
2221
"node-stream-zip": "^1.9.1",
2322
"ora": "^5.4.1",
24-
"prompts": "^2.4.0",
23+
"prompts": "^2.4.2",
2524
"semver": "^7.5.2",
2625
"strip-ansi": "^5.2.0",
2726
"sudo-prompt": "^9.0.0",
@@ -38,7 +37,7 @@
3837
"@types/command-exists": "^1.2.0",
3938
"@types/envinfo": "^7.8.1",
4039
"@types/ip": "^1.1.0",
41-
"@types/prompts": "^2.0.9",
40+
"@types/prompts": "^2.4.4",
4241
"@types/semver": "^6.0.2",
4342
"@types/wcwidth": "^1.0.0"
4443
},

packages/cli-doctor/src/tools/healthchecks/packager.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {
44
} from '@react-native-community/cli-tools';
55
import {HealthCheckInterface} from '../../types';
66
import {logManualInstallation} from './common';
7-
import {startServerInNewWindow} from '@react-native-community/cli-plugin-metro';
7+
import execa from 'execa';
8+
import path from 'path';
89

910
export default {
1011
label: 'Metro',
@@ -29,12 +30,14 @@ export default {
2930
const terminal = getDefaultUserTerminal();
3031
const port = Number(process.env.RCT_METRO_PORT) || 8081;
3132
if (terminal && config) {
32-
startServerInNewWindow(
33-
port,
33+
await execa('node', [
34+
path.join(config.reactNativePath, 'cli.js'),
35+
'start',
36+
'--port',
37+
port.toString(),
38+
'--terminal',
3439
terminal,
35-
config.root,
36-
config.reactNativePath,
37-
);
40+
]);
3841
return loader.succeed();
3942
}
4043
return logManualInstallation({

packages/cli-platform-android/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
"native_modules.gradle"
2121
],
2222
"devDependencies": {
23-
"@react-native-community/cli-plugin-metro": "12.0.0-alpha.8",
2423
"@react-native-community/cli-types": "12.0.0-alpha.8",
2524
"@types/fs-extra": "^8.1.0",
2625
"@types/glob": "^7.1.1"

packages/cli-platform-android/src/commands/buildAndroid/index.ts

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import {
22
CLIError,
3-
getDefaultUserTerminal,
4-
isPackagerRunning,
53
logger,
64
printRunDoctorTip,
75
} from '@react-native-community/cli-tools';
@@ -10,51 +8,17 @@ import execa from 'execa';
108
import {getAndroidProject} from '../../config/getAndroidProject';
119
import adb from '../runAndroid/adb';
1210
import getAdbPath from '../runAndroid/getAdbPath';
13-
import {startServerInNewWindow} from '@react-native-community/cli-plugin-metro';
1411
import {getTaskNames} from '../runAndroid/getTaskNames';
1512
import {promptForTaskSelection} from '../runAndroid/listAndroidTasks';
1613

1714
export interface BuildFlags {
1815
mode?: string;
1916
activeArchOnly?: boolean;
20-
packager?: boolean;
21-
port: number;
22-
terminal: string;
2317
tasks?: Array<string>;
2418
extraParams?: Array<string>;
2519
interactive?: boolean;
2620
}
2721

28-
export async function runPackager(args: BuildFlags, config: Config) {
29-
if (!args.packager) {
30-
return;
31-
}
32-
const result = await isPackagerRunning(args.port);
33-
if (result === 'running') {
34-
logger.info('JS server already running.');
35-
} else if (result === 'unrecognized') {
36-
logger.warn('JS server not recognized, continuing with build...');
37-
} else {
38-
// result == 'not_running'
39-
logger.info('Starting JS server...');
40-
41-
try {
42-
startServerInNewWindow(
43-
args.port,
44-
args.terminal,
45-
config.root,
46-
config.reactNativePath,
47-
);
48-
} catch (error) {
49-
if (error instanceof Error) {
50-
logger.warn(
51-
`Failed to automatically start the packager server. Please run "react-native start" manually. Error details: ${error.message}`,
52-
);
53-
}
54-
}
55-
}
56-
}
57-
5822
async function buildAndroid(
5923
_argv: Array<string>,
6024
config: Config,
@@ -112,7 +76,7 @@ async function buildAndroid(
11276
gradleArgs.push('-PreactNativeArchitectures=' + architectures.join(','));
11377
}
11478
}
115-
await runPackager(args, config);
79+
11680
return build(gradleArgs, androidProject.sourceDir);
11781
}
11882

@@ -137,21 +101,6 @@ export const options = [
137101
name: '--mode <string>',
138102
description: "Specify your app's build variant",
139103
},
140-
{
141-
name: '--no-packager',
142-
description: 'Do not launch packager while building',
143-
},
144-
{
145-
name: '--port <number>',
146-
default: process.env.RCT_METRO_PORT || 8081,
147-
parse: Number,
148-
},
149-
{
150-
name: '--terminal <string>',
151-
description:
152-
'Launches the Metro Bundler in a new window using the specified terminal path.',
153-
default: getDefaultUserTerminal(),
154-
},
155104
{
156105
name: '--tasks <list>',
157106
description:

packages/cli-platform-android/src/commands/runAndroid/index.ts

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,22 @@ import tryRunAdbReverse from './tryRunAdbReverse';
1313
import tryLaunchAppOnDevice from './tryLaunchAppOnDevice';
1414
import tryInstallAppOnDevice from './tryInstallAppOnDevice';
1515
import getAdbPath from './getAdbPath';
16-
import {logger, CLIError, link} from '@react-native-community/cli-tools';
16+
import {
17+
logger,
18+
CLIError,
19+
link,
20+
getDefaultUserTerminal,
21+
isPackagerRunning,
22+
logAlreadyRunningBundler,
23+
startServerInNewWindow,
24+
handlePortUnavailable,
25+
} from '@react-native-community/cli-tools';
1726
import {getAndroidProject} from '../../config/getAndroidProject';
1827
import listAndroidDevices from './listAndroidDevices';
1928
import tryLaunchEmulator from './tryLaunchEmulator';
2029
import chalk from 'chalk';
2130
import path from 'path';
22-
import {build, runPackager, BuildFlags, options} from '../buildAndroid';
31+
import {build, BuildFlags, options} from '../buildAndroid';
2332
import {promptForTaskSelection} from './listAndroidTasks';
2433
import {getTaskNames} from './getTaskNames';
2534
import {checkUsers, promptForUser} from './listAndroidUsers';
@@ -28,6 +37,9 @@ export interface Flags extends BuildFlags {
2837
appId: string;
2938
appIdSuffix: string;
3039
mainActivity: string;
40+
port: number;
41+
terminal?: string;
42+
packager?: boolean;
3143
deviceId?: string;
3244
listDevices?: boolean;
3345
binaryPath?: string;
@@ -42,6 +54,35 @@ export type AndroidProject = NonNullable<Config['project']['android']>;
4254
async function runAndroid(_argv: Array<string>, config: Config, args: Flags) {
4355
link.setPlatform('android');
4456

57+
let {packager, port} = args;
58+
59+
const packagerStatus = await isPackagerRunning(port);
60+
61+
if (
62+
typeof packagerStatus === 'object' &&
63+
packagerStatus.status === 'running'
64+
) {
65+
if (packagerStatus.root === config.root) {
66+
packager = false;
67+
logAlreadyRunningBundler(port);
68+
} else {
69+
const result = await handlePortUnavailable(port, config.root, packager);
70+
[port, packager] = [result.port, result.packager];
71+
}
72+
} else if (packagerStatus === 'unrecognized') {
73+
const result = await handlePortUnavailable(port, config.root, packager);
74+
[port, packager] = [result.port, result.packager];
75+
}
76+
77+
if (packager) {
78+
await startServerInNewWindow(
79+
port,
80+
config.root,
81+
config.reactNativePath,
82+
args.terminal,
83+
);
84+
}
85+
4586
if (config.reactNativeVersion !== 'unknown') {
4687
link.setVersion(config.reactNativeVersion);
4788
}
@@ -66,7 +107,6 @@ async function runAndroid(_argv: Array<string>, config: Config, args: Flags) {
66107

67108
const androidProject = getAndroidProject(config);
68109

69-
await runPackager(args, config);
70110
return buildAndRun(args, androidProject);
71111
}
72112

@@ -269,6 +309,21 @@ export default {
269309
func: runAndroid,
270310
options: [
271311
...options,
312+
{
313+
name: '--no-packager',
314+
description: 'Do not launch packager while running the app',
315+
},
316+
{
317+
name: '--port <number>',
318+
default: process.env.RCT_METRO_PORT || 8081,
319+
parse: Number,
320+
},
321+
{
322+
name: '--terminal <string>',
323+
description:
324+
'Launches the Metro Bundler in a new window using the specified terminal path.',
325+
default: getDefaultUserTerminal(),
326+
},
272327
{
273328
name: '--appId <string>',
274329
description:

packages/cli-platform-ios/src/commands/buildIOS/buildProject.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,9 @@ import {
1414
export type BuildFlags = {
1515
mode: string;
1616
target: string;
17-
packager: boolean;
1817
verbose: boolean;
1918
xcconfig?: string;
2019
buildFolder?: string;
21-
port: number;
22-
terminal: string | undefined;
2320
interactive?: boolean;
2421
destination?: string;
2522
extraParams?: string[];
@@ -72,6 +69,7 @@ export function buildProject(
7269
});
7370
}
7471
}
72+
7573
const buildProcess = child_process.spawn(
7674
'xcodebuild',
7775
xcodebuildArgs,
@@ -150,30 +148,32 @@ function xcprettyAvailable() {
150148
return true;
151149
}
152150

153-
function getProcessOptions({
154-
packager,
155-
terminal,
156-
port,
157-
}: {
158-
packager: boolean;
159-
terminal: string | undefined;
160-
port: number;
161-
}): SpawnOptionsWithoutStdio {
162-
if (packager) {
151+
function getProcessOptions<T extends BuildFlags>(
152+
args: T,
153+
): SpawnOptionsWithoutStdio {
154+
if (
155+
'packager' in args &&
156+
typeof args.packager === 'boolean' &&
157+
args.packager
158+
) {
159+
const terminal =
160+
'terminal' in args && typeof args.terminal === 'string'
161+
? args.terminal
162+
: '';
163+
164+
const port =
165+
'port' in args && typeof args.port === 'string' ? args.port : '';
166+
163167
return {
164168
env: {
165169
...process.env,
166170
RCT_TERMINAL: terminal,
167-
RCT_METRO_PORT: port.toString(),
171+
RCT_METRO_PORT: port,
168172
},
169173
};
170174
}
171175

172176
return {
173-
env: {
174-
...process.env,
175-
RCT_TERMINAL: terminal,
176-
RCT_NO_LAUNCH_PACKAGER: 'true',
177-
},
177+
env: process.env,
178178
};
179179
}

0 commit comments

Comments
 (0)