Skip to content

Commit 86522ec

Browse files
authored
fix: move start from @react-native/community-cli-plugin (#288)
* feat: move start from @react-native/community-cli-plugin * simplify, add todo * changeset * use single 'isDevServerRunning' implementation
1 parent bca367b commit 86522ec

19 files changed

Lines changed: 1002 additions & 249 deletions

.changeset/famous-zoos-mix.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@rnef/plugin-metro': patch
3+
---
4+
5+
feat: move start from @react-native/community-cli-plugin

packages/plugin-metro/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,13 @@
1515
"publish:verdaccio": "npm publish --registry http://localhost:4873 --userconfig ../../.npmrc"
1616
},
1717
"dependencies": {
18-
"@rnef/tools": "^0.7.2",
1918
"@react-native-community/cli-server-api": "^18.0.0",
19+
"@react-native/dev-middleware": "^0.79.1",
20+
"@rnef/tools": "^0.7.2",
21+
"metro": "^0.82.1",
22+
"metro-config": "^0.82.1",
23+
"metro-core": "^0.82.1",
24+
"metro-resolver": "^0.82.1",
2025
"tslib": "^2.3.0"
2126
},
2227
"devDependencies": {
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import fs from 'node:fs';
2+
import path from 'node:path';
3+
import {
4+
bundleCommand,
5+
// @ts-expect-error missing typings - TODO drop dependency on community plugin
6+
} from '@react-native/community-cli-plugin';
7+
import type { PluginApi } from '@rnef/config';
8+
import { color, intro, logger, outro, RnefError, runHermes, spinner } from '@rnef/tools';
9+
10+
type BundleCommandArgs = {
11+
assetsDest?: string;
12+
assetCatalogDest?: string;
13+
entryFile: string;
14+
resetCache: boolean;
15+
resetGlobalCache: boolean;
16+
transformer?: string;
17+
minify?: boolean;
18+
config?: string;
19+
platform: string;
20+
dev: boolean;
21+
bundleOutput: string;
22+
bundleEncoding?: 'utf8' | 'utf16le' | 'ascii';
23+
maxWorkers?: number;
24+
sourcemapOutput?: string;
25+
sourcemapSourcesRoot?: string;
26+
sourcemapUseAbsolutePath: boolean;
27+
verbose: boolean;
28+
unstableTransformProfile: string;
29+
indexedRamBundle?: boolean;
30+
resolverOption?: Array<string>;
31+
// custom flags
32+
hermes: boolean;
33+
};
34+
35+
export function registerBundleCommand(api: PluginApi) {
36+
api.registerCommand({
37+
name: 'bundle',
38+
description:
39+
'Build the bundle for the provided JavaScript entry file with Metro.',
40+
action: async (args: BundleCommandArgs) => {
41+
if (!args.platform || !args.bundleOutput || !args.entryFile) {
42+
throw new RnefError(
43+
'"rnef bundle" command requires all of these flags to bundle JavaScript with Metro: \n "--platform", "--bundle-output", "--entry-file"'
44+
);
45+
}
46+
intro('Compiling JS bundle with Metro');
47+
const root = api.getProjectRoot();
48+
const reactNativeVersion = api.getReactNativeVersion();
49+
const reactNativePath = api.getReactNativePath();
50+
const platforms = api.getPlatforms();
51+
52+
// create the bundle output directory if it doesn't exist
53+
const bundleOutputDir = path.dirname(args.bundleOutput);
54+
fs.mkdirSync(bundleOutputDir, { recursive: true });
55+
56+
await bundleCommand.func(
57+
undefined,
58+
{ root, reactNativeVersion, reactNativePath, platforms },
59+
args
60+
);
61+
62+
if (args.hermes) {
63+
const loader = spinner();
64+
loader.start('Running Hermes compiler...');
65+
await runHermes({ bundleOutputPath: args.bundleOutput });
66+
loader.stop(
67+
`Hermes bytecode bundle created at: ${color.cyan(args.bundleOutput)}`
68+
);
69+
} else {
70+
logger.info(
71+
`JavaScript bundle created at: ${color.cyan(args.bundleOutput)}`
72+
);
73+
}
74+
outro('Success 🎉.');
75+
},
76+
options: [
77+
...bundleCommand.options,
78+
{
79+
name: '--config-cmd [string]',
80+
description:
81+
'[Internal] A hack for Xcode build script pointing to wrong bundle command that recognizes this flag. Do not use.',
82+
},
83+
{
84+
name: '--hermes',
85+
description:
86+
'Passes the output JS bundle to Hermes compiler and outputs a bytecode file.',
87+
},
88+
],
89+
});
90+
}

packages/plugin-metro/src/lib/pluginMetro.ts

Lines changed: 5 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -1,176 +1,12 @@
1-
import { mkdirSync } from 'node:fs';
2-
import path from 'node:path';
3-
import {
4-
bundleCommand,
5-
startCommand,
6-
// @ts-expect-error missing typings
7-
} from '@react-native/community-cli-plugin';
81
import type { PluginApi, PluginOutput } from '@rnef/config';
9-
import {
10-
color,
11-
findDevServerPort,
12-
intro,
13-
logger,
14-
outro,
15-
RnefError,
16-
runHermes,
17-
spinner,
18-
} from '@rnef/tools';
19-
20-
type PluginConfig = {
21-
reactNativeVersion?: string;
22-
reactNativePath?: string;
23-
platforms?: {
24-
[platformName: string]: object;
25-
};
26-
};
27-
28-
type StartCommandArgs = {
29-
assetPlugins?: string[];
30-
cert?: string;
31-
customLogReporterPath?: string;
32-
host?: string;
33-
https?: boolean;
34-
maxWorkers?: number;
35-
key?: string;
36-
platforms: string[];
37-
port?: number;
38-
resetCache?: boolean;
39-
sourceExts?: string[];
40-
transformer?: string;
41-
watchFolders?: string[];
42-
config?: string;
43-
projectRoot?: string;
44-
clientLogs?: boolean;
45-
interactive: boolean;
46-
};
47-
48-
type BundleCommandArgs = {
49-
assetsDest?: string;
50-
assetCatalogDest?: string;
51-
entryFile: string;
52-
resetCache: boolean;
53-
resetGlobalCache: boolean;
54-
transformer?: string;
55-
minify?: boolean;
56-
config?: string;
57-
platform: string;
58-
dev: boolean;
59-
bundleOutput: string;
60-
bundleEncoding?: 'utf8' | 'utf16le' | 'ascii';
61-
maxWorkers?: number;
62-
sourcemapOutput?: string;
63-
sourcemapSourcesRoot?: string;
64-
sourcemapUseAbsolutePath: boolean;
65-
verbose: boolean;
66-
unstableTransformProfile: string;
67-
indexedRamBundle?: boolean;
68-
resolverOption?: Array<string>;
69-
// custom flags
70-
hermes: boolean;
71-
};
2+
import { registerBundleCommand } from './bundle/command.js';
3+
import { registerStartCommand } from './start/command.js';
724

735
export const pluginMetro =
74-
(pluginConfig: PluginConfig = {}) =>
6+
() =>
757
(api: PluginApi): PluginOutput => {
76-
api.registerCommand({
77-
name: 'start',
78-
description: 'Starts Metro dev server.',
79-
action: async (args: StartCommandArgs) => {
80-
const root = api.getProjectRoot();
81-
const reactNativeVersion = api.getReactNativeVersion();
82-
const reactNativePath = api.getReactNativePath();
83-
const platforms = api.getPlatforms();
84-
85-
const { port, startDevServer } = await findDevServerPort(
86-
args.port ?? 8081,
87-
root
88-
);
89-
90-
if (!startDevServer) {
91-
return;
92-
}
93-
94-
startCommand.func(
95-
undefined,
96-
{
97-
root,
98-
reactNativeVersion,
99-
reactNativePath,
100-
platforms,
101-
...pluginConfig,
102-
},
103-
{
104-
...args,
105-
port,
106-
}
107-
);
108-
},
109-
options: startCommand.options,
110-
});
111-
112-
api.registerCommand({
113-
name: 'bundle',
114-
description:
115-
'Build the bundle for the provided JavaScript entry file with Metro.',
116-
action: async (args: BundleCommandArgs) => {
117-
if (!args.platform || !args.bundleOutput || !args.entryFile) {
118-
throw new RnefError(
119-
'"rnef bundle" command requires all of these flags to bundle JavaScript with Metro: \n "--platform", "--bundle-output", "--entry-file"'
120-
);
121-
}
122-
intro('Compiling JS bundle with Metro');
123-
const root = api.getProjectRoot();
124-
const reactNativeVersion = api.getReactNativeVersion();
125-
const reactNativePath = api.getReactNativePath();
126-
const platforms = api.getPlatforms();
127-
128-
// create the bundle output directory if it doesn't exist
129-
const bundleOutputDir = path.dirname(args.bundleOutput);
130-
mkdirSync(bundleOutputDir, { recursive: true });
131-
132-
await bundleCommand.func(
133-
undefined,
134-
{
135-
root,
136-
reactNativeVersion,
137-
reactNativePath,
138-
platforms,
139-
...pluginConfig,
140-
},
141-
args
142-
);
143-
144-
if (args.hermes) {
145-
const loader = spinner();
146-
loader.start('Running Hermes compiler...');
147-
await runHermes({ bundleOutputPath: args.bundleOutput });
148-
loader.stop(
149-
`Hermes bytecode bundle created at: ${color.cyan(
150-
args.bundleOutput
151-
)}`
152-
);
153-
} else {
154-
logger.info(
155-
`JavaScript bundle created at: ${color.cyan(args.bundleOutput)}`
156-
);
157-
}
158-
outro('Success 🎉.');
159-
},
160-
options: [
161-
...bundleCommand.options,
162-
{
163-
name: '--config-cmd [string]',
164-
description:
165-
'[Internal] A hack for Xcode build script pointing to wrong bundle command that recognizes this flag. Do not use.',
166-
},
167-
{
168-
name: '--hermes',
169-
description:
170-
'Passes the output JS bundle to Hermes compiler and outputs a bytecode file.',
171-
},
172-
],
173-
});
8+
registerStartCommand(api);
9+
registerBundleCommand(api);
17410

17511
return {
17612
name: '@rnef/plugin-metro',

0 commit comments

Comments
 (0)