discussions-and-proposals icon indicating copy to clipboard operation
discussions-and-proposals copied to clipboard

Improving the React Native command line experience

Open molant opened this issue 4 years ago β€’ 7 comments

React Native and command line experience(s)

The RN community has a wide variety of command line tools (react-native-community/cli, create-react-native-app, expo-cli, ignite-cli, etc.). While all have unique features (templates, environment validation, generators, etc...), feature overlap causes confusing and unnecessary cognitive overheard to developers. In addition, a lot of documentation is a bit outdated and can be a detriment to new developers getting started with React Native. One of the main reasons we've learned that developers end up using different technologies is because React Native does not feel well integrated.

There have been some conversations in Discord about what could be done to improve this situation and the immediate outcome was to move this conversation to a public forum, discuss what things are important to each of us, and agree on a set of features and collectively decide how to get there.

What are the must have features you would like to see in this CLI?

From Microsoft's side these are the things that are important to us:

  • Better support for out-of-tree platforms: Web, Windows, macOS, etc. There's some discussions and work already done, but it would be great to make it easier for projects to initialize with out-of-tree platforms, and to easily add them to existing ones.

  • Easy on-boarding: Setting up the environment correctly can take some time and is error prone. With the new out-of-tree platforms users will have even more requirements. We would like for a way to automatically check and install pre-requisites that are also tied to the platforms the user wants to target.

  • Improve the debugging and editing experience: From our research, debugging (JS or native code) is the top issue of React Native developers. VS Code is one of the most popular editors (if not the most) to write React Native applications. We already have a VS Code extension that allows debugging RN and Expo apps but configuring it correctly can be complicated the first time (especially when there's transpilation involved). Also, for developers looking at using TypeScript there is conflicting documentation on what is the proper way to add it. Same as out-of-tree platforms it will be great to give developers an easy way to enable this scenario (and other similar things) when initializing a project.

So the above would translate into:

  1. Fast and lightweight: npx is the "defacto-standard" to run most of the current solutions so we would like to make it as lean and fast as possible.
  2. Pluggable: The current react-native-community/cli allows for adding run-XXX parameters, but there are other aspects that are more "monolithic": init and doctor are the most obvious, but we might want to have an option to add or extend other commands.
  3. Shareable components: Splitting into multiple packages so they are easier to maintain and can be reused by other tools. This should also help with 1.
  4. Documented: We want developers to take advantage of the pluggability aspect. We should document things along the way so it's easier for them to write plugins and contribute back.

What are the things that are important to you that are not in here?

molant avatar May 27 '20 17:05 molant

Templates for monorepo / multi-platform apps ? (I don't know if this fits in the scope of CLI experience)

wynch avatar May 27 '20 19:05 wynch

This is awesome! Here's my wish list off the top of my head:

  • When adding a new third party RN dependency it will auto link on Android (because gradle) but for iOS you gotta do cd ios && pod install. It would be neat if the CLI could handle this in some way like detecting that a pod install is required when yarn ios is run.

  • +1 for improved template/TypeScript support. I really like the wizard style of expo CLI init command. For instance it asks you if you want a TypeScript project (which I always do ☺️). The RN CLI could suggest the RN community TypeScript template be used when running react-native init for example. I also think the default project which gets generated could make use of a .vscode/ configuration if specified by the developer. The first thing I do when creating a new project is create a .vscode/ folder with a settings.json, extensions.json and launch.json. If the CLI did this you'd get things like auto lint/prettier on save and the RN VSCode extension setup out of the box.

  • When running on a physical Android device I always forget I need to do adb reverse. It would be awesome to bake this into the CLI when running yarn android

  • We have a clean command at Hudl for our RN projects which deletes node_modules, iOS derived data, Android build folders etc. This comes in real handy more often than you'd think. Would be awesome if that was part of the CLI also.

  • We also have a command for working with Android emulators e.g. listing the installing emulators, starting a specific one. I believe the RN CLI now starts an Android emulator when doing yarn android but I'm not sure it supports listing installed emulators, or starting them outside of the main Android command. We also have a flag which wipes the emulator on start up if needed. That comes in handy.

  • The CLI might already support this in a nice way but there's times I just wanna delete the android/ and ios/ directories and regenerate them based on the rest of my project. I know I can just init a new project with the same name and copy the folders across but I'd like to be able to just run a command from the CLI which deletes and regens my native projects.

I'm sure more things will pop into my head but those were the main things that came to mind πŸ‘.

mrbrentkelly avatar May 27 '20 20:05 mrbrentkelly

Thought of a few more this morning πŸ˜„:

  • Being able to init a RN library project. In the past when I've created an RN library I've had to turn to third party tools like create-react-native-module (which have worked great btw). It would be pretty neat if the main RN CLI had this functionality baked in. Might be a good way to promote consistency of RN Library projects directly from the React Native Community.

  • When running npx react-native init it can take a few minutes, partly because of the initial pod install. I might not run yarn ios right away (or ever if I'm gonna target RN Windows) so it could be cool to defer pod install until it's required (when running yarn ios for the first time for example) and save some time during init. Things like this could get the init times closer to create-react-native-app which feels super fast.

  • Improved --template support for private template repos. This could work already but I've had trouble getting the --template flag to work with private RN template repos. Instead I have to git clone the template repo first and pass a local path to the --template flag (i.e. npx react-native init SomeApp --template file:$PWD/a-private-template.

mrbrentkelly avatar May 28 '20 06:05 mrbrentkelly

I'd like to see improvements to the Metro bundler:

  • Errors during bundling can be super difficult to diagnose as the output from an error is typically coming from an exception from deep inside the Metro code. Typically developers are not actually diagnosing these cryptic errors, instead they are solved through social engineering (eg doing a google search). The error messages could be improved to become more actionable. More validation of the configuration could be done up front as Metro is starting up, and the error messages could tell developers what they did wrong with their configuration.
  • A good number of Metro options are not documented, or are only partially documented. In addition, the docs on the repo aren't particularly verbose or helpful. This comment applies to both the command-line args as well as the configuration options in metro.config.js. I'd love to see guides created to show developers how to setup a correct configuration, what to expect if something goes wrong, and steps to take to diagnose errors.
  • On Windows, file names are case insensitive, but Metro treats all filenames as case sensitive. This can lead to hard-to-diagnose errors at bundle time if the metro config contains paths that don't consistently use the same case as Metro does internally (in general file/directory names are expected to the same case as were originally saved to disk). Metro should be improved on Windows (or any other platform like Windows) to not make the assumption that all paths are case-sensitive.

kmelmon avatar Jun 01 '20 23:06 kmelmon

This is a very broad topic, so I'll focus in on one aspect of the CLI experience in this comment - the project initialization experience. From Expo's side these are the that are important to us:

  • Langauges should reflect what is used in the ecosystem: projects should be initialized as plain JS (not Flow) to be welcoming to beginners, with an easy to discover option (or global configuration) to use TypeScript or Flow instead. Realistically, Flow usage should probably be discouraged because it is not widely supported in the ecosystem. As more folks move towards using Swift and Kotlin, the templates should switch to reflect that.
  • Default to a widely supported React Native version: when a new release of React Native ships there is a period of time in which many libraries, the Expo managed workflow, and out-of-tree-platforms aren't supported. We think it's not a great experience to introduce new users on the latest release the day or week or sometimes even month that it is shipped, but rather to wait until there is more broad support in the ecosystem until it's the default. Usually this means that the release would be one version behind upstream.
  • Support for Expo modules: developers currently need to install react-native-unimodules in their projects in order to use libraries from the Expo SDK. This, unfortunately, includes some additional configuration that can discourage users from using a library from the Expo SDK even if it happens to be the best solution to their problem.
  • Out-of-tree-platform support: we are most interested in web, and we've invested a lot of time in making React Native Web work great out of the box in any React Native project.
  • Fast: there's no good reason why initializing React Native projects should take an order of magnitude longer than a CRA project on a fast connection, aside from the pod install step. As mentioned above by @mrbrentkelly, create-react-native-app is fast and the reason is that it has minimal dependencies and is focused entirely on initializing the app.
  • Integration with template repositories inspired by create-next-app, it should be easy to search from a list of well maintained and curated example projects that get the developer started from with some common configurations (for example, run npx create-react-native-app or npx crna for short and choose "Template from expo/examples").

What I have described above is essentially what guided our design for create-react-native-app. This solves all of our problems very well, but it conflicts with the goal of minimizing the number of entry points and decisions that users need to make. If we were to converge onto a single tool for initialziing projects, there may be some conflicting priorities regarding the selection of defaults:

  • Facebook may want to stick with the latest React Native versions by default. They may also only want to include React Native iOS and Android, because those are the platforms that they maintain.
  • Microsoft may want to default to TypeScript, and may not want to default to support Expo modules because they do not run on React Native for MacOS or Windows currently, and may want to pull examples from a repository that they maintain.
  • Expo would like to default to support for Expo modules and to pull from the examples repository that we maintain. We would also like to include web by default, which may not be something that other folks are interested in.
  • Other tool maintainers such as @jamonholmgren may find that consolidation into this tool limits his ability to provide the highly interactive initialization experience that Ignite currently provides.

brentvatne avatar Jun 09 '20 22:06 brentvatne

I'll add to what @brentvatne said from the context of Ignite CLI:

I'm current exploring moving Ignite over to using React Native templates, so we don't have to use our own template format (currently .ejs files with an Ignite CLI boilerplate.js script to generate them). However, I'm running into a few issues.

  1. We have a walkthrough when generating a new project (like @mrbrentkelly mentioned Expo has). But RN templates currently don't have a good way to add logic into files. See example below.
  2. Ignite CLI currently supports Expo or vanilla RN init with the same boilerplate. Given that Expo templates are different than RN cli templates, I don't see an obvious way to do that right now.

Example:

If the user chooses to integrate Detox into their Ignite Bowser app, we conditionally add certain lines of code to certain files.

  "scripts": {
<% if (props.includeDetox) { -%>
    "test:e2e": "detox test -c ios.sim.debug",
    "build:e2e": "detox build -c ios.sim.debug",
    "ci:test:e2e": "detox test -c ios.sim.release -l verbose --cleanup",
    "ci:build:e2e": "detox build -c ios.sim.release",
<% } -%>
    "compile": "tsc --noEmit -p . --pretty",

I'm very happy to see this discussion, though! I'm very interested in making Ignite CLI simpler and easier to work on, and pushing some of that capability upstream would be a good move that direction.

jamonholmgren avatar Jun 13 '20 21:06 jamonholmgren

eject should be also in place by default all the time. It is easy to remove or break android/ or ios/ project. There should be some easy way to fix / recreate it :-) https://github.com/facebook/react-native/issues/32109

cederom avatar Aug 29 '21 01:08 cederom