Skip to content

Contributing to the CLI

Jon Thysell edited this page Jun 8, 2022 · 32 revisions

Where stuff lives

Parts of the CLI:

  1. Code to identify the correct version of react-native-windows to install, and install it:
    [Root]\packages\react-native-windows-init
  2. Template code: The code that actually creates the files needed to to run a create and run react-native-windows app here:
    [Root]\packages\@react-native-windows\cli
  3. Template files used in (2) can be found in:
    [Root]\vnext\templates
  4. Code for run-windows and other commands run through react-native <foo> Also in [Root]\packages\@react-native-windows\cli

Locally testing changes to the new project CLI

Testing react-native-windows-init itself

If you are making local changes to the react-native-windows-init code, you can build and run it locally:

  1. Build the react-native-windows-init package locally using yarn build
  2. Manually call into the CLI by using node <root>\packages\react-native-windows-init\bin.js [...] rather than calling npx react-native-windows-init [...]

Note, you can pass parameters to that as usual, or use node --inspect-brk ... to allow you to attach to the call using VSCode.

Also note that this will only test the changes made directly to the react-native-windows-init package. The other packages will be downloaded from npmjs.org (according to the version you specified with --version) during the process.

Testing changes made to our other packages using --useDevMode

If you have made local changes to react-native-windows, @react-native-windows/cli, (or any other package in our repo), you can use a combination of yarn link and the --useDevMode flag to make sure the local version of all of our packages are being used when creating a new project.

  1. Build your RNW repo with yarn build
  2. Run yarn link in <root>\vnext to link react-native-windows

    If you get an error that another folder has already registered it simply run yarn unlink and then try again.

  3. Open the target RN project (app/lib) folder
  4. Call npx react-native-windows-init --useDevMode [...], being sure to not specify a version, since you're trying to use your local copy

Note, you can also call node <root>\packages\react-native-windows-init\bin.js --useDevMode [...] as per the above example, to use your local copy of react-native-windows-init, rather than the one published to npmjs.org.

How --useDevMode works

When calling react-native-windows-init with --useDevMode, instead of calling yarn add to add the react-native-windows dependency and downloading it, the command uses yarn link instead, expecting that you've already linked your local copy of react-native-windows.

This use of linking react-native-windows has some unexpected side-effects. Your app will now consume your local copy of react-native-windows via a symlink in node_modules, but will still appear to install all of the other dependencies like @react-native/cli from npmjs.org.

However, those packages will never actually get used. When react-native-windows-init continues its work and tries to generate the windows project, it will use your local RNW repo's copy of @react-native-windows/cli, not the one that was just installed into node_modules. This happens because the entry-point for the react-native CLI, vnext\react-native.config.js, calls require("@react-native-windows/cli") which gets your RNW repo's local version.

Furthermore, when you later make calls to other CLI commands, like react-native run-windows or react-native config, again this redirection happens, looking at your local RNW repo's copy of @react-native-windows/cli. This is useful because it allows you to test any changes made to that local repo's copy. However, it's good to keep in mind that there are these unused packages installed in node_modules.

How to debug other CLI commands:

The easiest way to to debug is using VS Code. You just need to create a configuration within your template app directory that tells VS Code to launch the CLI in an instance of node and debug node on startup. Here's an example launch.json with a single configuration:

{
  "version": "0.2.0",
  "configurations"[
    {
      "type""node",
      "request""launch",
      "name""react-native windows",
      "program""${workspaceRoot}/node_modules/react-native/cli.js",
      "args"["run-windows"],
      "stopOnEntry"true
    }
  ],
  "compounds"[]
}