Skip to content
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

Add option to override default metro config #207

Merged
merged 3 commits into from
May 10, 2024
Merged
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
8 changes: 6 additions & 2 deletions packages/docs/docs/launch-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,12 @@ Below is an example of how the `launch.json` file could look like with android v
Here, we list other attributes that can be configured using launch configuration which doesn't fit in any of the above categories:

- `appRoot` – Location of the React Native application root folder relative to the workspace. This is used for monorepo type setups when the workspace root is not the root of the React Native project. The IDE extension tries to locate the React Native application root automatically, but in case it failes to do so (i.e. there are multiple applications defined in the workspace), you can use this setting to override the location.
- `env` – Environment variables to be passed to all build/run commands that the IDE is launching.
- `env` – Environment variables to be passed to all build/run commands that the
IDE is launching.
- `metroConfigPath` — Path to metro config relative to the workspace. By default it tries to find
`metro.config.js` or `metro.config.ts`.

Below is a sample `launch.json` config file with `appRoot` and `env` setting specified:
Below is a sample `launch.json` config file with `appRoot`, `metroConfigPath`, and `env` setting specified:

```json
{
Expand All @@ -140,6 +143,7 @@ Below is a sample `launch.json` config file with `appRoot` and `env` setting spe
"request": "launch",
"name": "React Native IDE panel",
"appRoot": "packages/mobile",
"metroConfigPath": "metro.config.dev.js",
"env": {
"MY_SECRET_KEY": "bananas"
}
Expand Down
7 changes: 6 additions & 1 deletion packages/vscode-extension/lib/metro_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ const { adaptMetroConfig, requireFromAppDir, metroServerReadyHandler } = require
const { loadConfig } = requireFromAppDir("metro-config");

module.exports = async function () {
const config = await loadConfig({}, {});
const customMetroConfigPath = process.env.RN_IDE_METRO_CONFIG_PATH;
let options = {};
if (customMetroConfigPath) {
options = { config: customMetroConfigPath };
}
const config = await loadConfig(options, {});
return adaptMetroConfig(config);
};
4 changes: 4 additions & 0 deletions packages/vscode-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@
"type": "object",
"description": "Environment variables to be passed to all build/run commands that the IDE is launching."
},
"metroConfigPath": {
"type": "string",
"description": "Location of Metro config relative to the workspace. This is used for using custom configs for e.g. development."
},
"ios": {
"description": "Provides a way to customize Xcode builds for iOS",
"type": "object",
Expand Down
15 changes: 3 additions & 12 deletions packages/vscode-extension/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import fs from "fs";
import { SidePanelViewProvider } from "./panels/SidepanelViewProvider";
import { PanelLocation } from "./common/WorkspaceConfig";
import { getLaunchConfiguration } from "./utilities/launchConfiguration";
import { getTelemetryReporter } from "./utilities/telemetry";
import { findSingleFileInWorkspace } from "./utilities/common";

const BIN_MODIFICATION_DATE_KEY = "bin_modification_date";
const OPEN_PANEL_ON_ACTIVATION = "open_panel_on_activation";
Expand Down Expand Up @@ -145,16 +145,6 @@ export async function activate(context: ExtensionContext) {
await configureAppRootFolder();
}

async function findSingleFileInWorkspace(fileGlobPattern: string, excludePattern: string | null) {
const files = await workspace.findFiles(fileGlobPattern, excludePattern, 2);
if (files.length === 1) {
return files[0];
} else if (files.length > 1) {
Logger.error(`Found multiple ${fileGlobPattern} files in the workspace`);
}
return undefined;
}

function extensionActivated() {
if (extensionContext.workspaceState.get(OPEN_PANEL_ON_ACTIVATION)) {
commands.executeCommand("RNIDE.openPanel");
Expand All @@ -173,7 +163,8 @@ async function configureAppRootFolder() {
}

async function findAppRootFolder() {
const appRootFromLaunchConfig = getLaunchConfiguration().appRoot;
const launchConfiguration = getLaunchConfiguration();
const appRootFromLaunchConfig = launchConfiguration.appRoot;
if (appRootFromLaunchConfig) {
let appRoot: string | undefined;
workspace.workspaceFolders?.forEach((folder) => {
Expand Down
24 changes: 20 additions & 4 deletions packages/vscode-extension/src/project/metro.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import path from "path";
import { Disposable } from "vscode";
import { Disposable, Uri, workspace } from "vscode";
import { exec, ChildProcess, lineReader } from "../utilities/subprocess";
import { Logger } from "../Logger";
import { extensionContext, getAppRootFolder } from "../utilities/extensionContext";
import { Devtools } from "./devtools";
import stripAnsi from "strip-ansi";
import { getLaunchConfiguration } from "../utilities/launchConfiguration";
import fs from "fs";

export interface MetroDelegate {
onBundleError(): void;
Expand Down Expand Up @@ -127,14 +128,19 @@ export class Metro implements Disposable {
resetCache: boolean,
progressListener: (newStageProgress: number) => void
) {
let appRootFolder = getAppRootFolder();
const appRootFolder = getAppRootFolder();
const launchConfiguration = getLaunchConfiguration();
await this.devtools.ready();

const libPath = path.join(extensionContext.extensionPath, "lib");

let metroConfigPath: string | undefined;
if (launchConfiguration.metroConfigPath) {
metroConfigPath = findCustomMetroConfig(launchConfiguration.metroConfigPath);
}
const metroEnv = {
...process.env,
...getLaunchConfiguration().env,
...launchConfiguration.env,
...(metroConfigPath ? { RN_IDE_METRO_CONFIG_PATH: metroConfigPath } : {}),
NODE_PATH: path.join(appRootFolder, "node_modules"),
RCT_METRO_PORT: "0",
RCT_DEVTOOLS_PORT: this.devtools.port.toString(),
Expand Down Expand Up @@ -251,6 +257,16 @@ export class Metro implements Disposable {
}
}

function findCustomMetroConfig(configPath: string) {
for (const folder of workspace.workspaceFolders ?? []) {
const possibleMetroConfigLocation = Uri.joinPath(folder.uri, configPath);
if (fs.existsSync(possibleMetroConfigLocation.fsPath)) {
return possibleMetroConfigLocation.fsPath;
}
}
throw new Error("Metro config cannot be found, please check if `metroConfigPath` path is valid");
}

function shouldUseExpoCLI() {
// for expo launcher we use expo_start.js script that override some metro settings since it is not possible to
// do that by passing command line option like in the case of community CLI's packager script.
Expand Down
15 changes: 15 additions & 0 deletions packages/vscode-extension/src/utilities/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { Readable } from "stream";
import { finished } from "stream/promises";
import fs from "fs";
import { ReadableStream } from "stream/web";
import { workspace } from "vscode";
import { Logger } from "../Logger";

export enum CPU_ARCHITECTURE {
ARM64 = "arm64-v8a",
Expand All @@ -18,6 +20,19 @@ export function getDevServerScriptUrl() {
return process.env.DEV_SCRIPT_URL;
}

export async function findSingleFileInWorkspace(
fileGlobPattern: string,
excludePattern: string | null
) {
const files = await workspace.findFiles(fileGlobPattern, excludePattern, 2);
if (files.length === 1) {
return files[0];
} else if (files.length > 1) {
Logger.error(`Found multiple ${fileGlobPattern} files in the workspace`);
}
return undefined;
}

export function getCpuArchitecture() {
const arch = os.arch();
switch (arch) {
Expand Down
31 changes: 13 additions & 18 deletions packages/vscode-extension/src/utilities/launchConfiguration.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
import { workspace } from "vscode";

export type LaunchConfigurationOptions = {
appRoot: string | undefined;
env: Record<string, string> | undefined;
ios:
| {
scheme: string | undefined;
configuration: string | undefined;
}
| undefined;
android:
| {
variant: string | undefined;
}
| undefined;
preview:
| {
waitForAppLaunch: boolean | undefined;
}
| undefined;
appRoot?: string;
jakub-gonet marked this conversation as resolved.
Show resolved Hide resolved
metroConfigPath?: string;
env?: Record<string, string>;
ios?: {
scheme?: string;
configuration?: string;
};
android?: {
variant?: string;
};
preview?: {
waitForAppLaunch?: boolean;
};
};

export function getLaunchConfiguration(): LaunchConfigurationOptions {
Expand Down
Loading