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 React-Native schematics or other integration #1860

Closed
4 tasks done
asherccohen opened this issue Sep 18, 2019 · 46 comments
Closed
4 tasks done

Add React-Native schematics or other integration #1860

asherccohen opened this issue Sep 18, 2019 · 46 comments
Assignees
Labels
outdated scope: react Issues related to React support for Nx type: feature

Comments

@asherccohen
Copy link

  • I am running the latest version
  • I checked the documentation and found no answer
  • I checked to make sure that this issue has not already been filed
  • I'm reporting the issue to the correct repository (not related to Angular, AngularCLI or any dependency)

Expected Behavior

There are no schematics for React-Native.

Current Behavior

React-Native cannot be added to nx workspace.

Failure Information (for bugs)

As monorepos are getting more and more popular it's possible to find resources and articles online to share components between react-for-web an react-native. This is trivial in reducing time consuming for smaller teams in dare need to build cross-platform solutions.

It would be great to add capabilities to nx workspaces to kick-off a react-native application.

Steps to Reproduce

These are the steps needed to have a RN application building with nx. To achieve this I have manually added react-native to an existing nx workspace and worked my way to change all node-modules references to build from the root folder.

I have tested this ONLY on Android so uncertain the build works on iOS at the time of writing.

  1. I assume you have a working nx workspace
  2. I assume you have react-native CLI globally installed, both Xcode and Android Studio configured as following docs https://facebook.github.io/react-native/docs/getting-started
  3. cd into the apps folder
  4. run react-native init myproject (make sure to select a project name that follows npm guidelines)
  5. we will use yarn workspaces to unify package.json so add these to the project's root package.json:
    "workspaces": { "apps": [ "apps/*" ], "nohoist": [] }
  6. run yarn install
  7. Check where react-native got installed. If it was at /node_modules/react-native, all right. If it was at /packages/mobile/node_modules/react-native, something is wrong. Make sure you have the latest versions of node and yarn.
  8. Now we need to change some references to point to the correct node_modules folder. Specifically the files to change are:

-apps\myproject \android\app\build.gradle

project.ext.react = [ entryFile: "apps/earthonfire/index.js", root: "../../../../../", enableHermes: false, // clean and rebuild if changing ] apply from: "../../../../node_modules/react-native/react.gradle"

-apps\myproject \android\build.gradle

repositories { mavenLocal() maven { url("$rootDir/../../../node_modules/react-native/android") } maven { url("$rootDir/../../../node_modules/jsc-android/dist") } google() jcenter() }

-apps\myproject \android\settings.gradle (this is very important, see this thread why facebook/react-native#25479):

rootProject.name = 'earthonfire' apply from: file("../../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings, "../../apps/myproject") include ':app'

-apps\myproject \android\app\src\main\java\com\myproject\MainApplication.java

@Override protected String getJSMainModuleName() { return "apps/myproject/index"; }

  1. Open packages/mobile/package.json. Your start script currently ends in /cli.js start. Append this to the end: --projectRoot ../../.

  2. If this file exists (apps\myproject \metro.config.js), set the projectRoot field on it as well so it looks like this (the important part is the path module import and the projectRoot setting):
    const path = require('path'); module.exports = { projectRoot: path.resolve(__dirname, '../../../'), transformer: { getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, inlineRequires: false, }, }), }, };

  3. The cleanest solution is to have a package.json file in the RN folder and run all commands from there. Trying to do it from the root folder may lead to different results. You need to build with yarn run-android and then start metro bundler.
    My case was to have a run-android custom script to point to the correct node_modules like this (the --no-jetifier flag is needed as I had errors in running this tool)
    "run-android": "node ../../node_modules/react-native/local-cli/cli.js run-android --no-jetifier",
    and
    "start": "node ../../node_modules/react-native/local-cli/cli.js start --projectRoot ../../",

I also tried not using a package.json in the RN folder, it would build but then metro bundler would fail missing a dependency such as @babel/runtime/helpers/interopRequireDefault. I added the dependency but no solution was found.

Context

Please provide any relevant information about your setup:

  • version of Nx used 'latest'
  • 3rd-party libraries and their versions: "react-native": "0.60.5",
@jbuijgers
Copy link

Based on your example, I've managed to get it to work for react-native v0.61.1. The interopRequireDefault error might be due to the Metro Bundler not being able to find the node_modules directory. I had the same issue, which I fixed by adding node_modules to the watchFolders settings in metro.config.js.

Also added libs to metro.config.js here.

const path = require('path');
const libs = path.resolve(__dirname, '../../libs');

module.exports = {
  watchFolders: [path.resolve(__dirname, '../../node_modules'), libs],
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: false
      }
    })
  }
};

The following babel.config.js is needed to get libs working.

const path = require('path');
const libs = path.resolve(__dirname, '../../libs');

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: [
    [
      'module-resolver',
      {
        root: ['.'],
        alias: {
          '^@nx-rn-test/(.+)': libs + '/\\1/src'
        }
      }
    ]
  ]
};

I did have a slightly different approach, where I did not maintain a separate package.json, but just used the package.json in the workspace root.

I also changed the following at the end of android/app/build.gradle, note the second argument. Based on react-native-cli Autolinking docs.

applyNativeModulesAppBuildGradle(project, "../../..")

I used the following commands to run the react-native app, in the given order.

react-native start --config apps/mobile/metro.config.js --reset-cache
react-native run-android --root apps/mobile

Currently loading (certain) assets does not seem to work, I'm running the react-native boilerplate (the one you get after react-native init), and am getting a 404 while it's trying to load the /node_modules/react-native/Libraries/NewAppScreen/components/logo.png file. The Metro Bundler is also giving "transform[stderr]: Could not resolve ..." error, but it does not seem to fail on that and everything seems to just work.

Hope this is helpful in getting your example working @asherccohen , would love to help in getting working schematics for react-native.

@asherccohen
Copy link
Author

Super!Thanks a lot @jbuijgers for looking into this. Yes indeed a working schematics would be very useful.
@jaysoo is also suggesting some run-commands and will be looking into this.
Stay tuned!

@jbuijgers
Copy link

Hi all, I got a prototype (only Android atm) going at https://github.com/JBuijgers/nx-react-native, also published it on NPM https://www.npmjs.com/package/@jbuijgers/nx-react-native. So far it works, but it still needs work/testing before it's fully usable. I'll be adding iOS in the coming week. Would love to get some feedback on this.

@jaysoo jaysoo added the scope: react Issues related to React support for Nx label Oct 24, 2019
@jaysoo jaysoo self-assigned this Oct 29, 2019
@IIslam
Copy link

IIslam commented Nov 18, 2019

@jaysoo It would be great if expo and expo-cli is being embedded as well.

@iangregsondev
Copy link

Yep - the expo would be great, I already tried using the BUILDER - run-command offered by @nrwl/workspaces - but I couldn't get it to work.

I think all that would be needed is to run the expo cli commands on serve / build etc

@asherccohen
Copy link
Author

@jbuijgers Greta job, do you have any update on this?
I've tried your package and I'm stuck at an error (but surely not related to your work):

  • Where:
    Script 'C:\Users\asher\Documents\Projects_live\Monorepo\code-tank\node_modules@react-native-community\cli-platform-android\native_modules.gradle' line: 170

  • What went wrong:
    A problem occurred evaluating script.

Command config unrecognized. Make sure that you have run npm install and that you are inside a react-native project.

@iangregsondev
Copy link

I have abandoned trying to run the react-native expo via nx tools. Although I am still using NX as a structure.

What I did was retain the package.json under my apps/rn (where my react native app sits inside of the nx structure). The package.json comes from creating a branch new expo project using the expo cli.

I tried many ways of trying to install the expo etc inside the root of the package.json but a lot of things are hardcoded. Even if I got it to work, it kind of feels hacky and who knows if it breaks in the future.

So now I am basically npm installing all libraries in root (nx) as per normal but anything related to expo under the apps/rn

In effect I am maintaining 2 x package.json / node_modules - but this was the only way to get it to work :-(

It seems to be working correctly now

I am using the standard expo start - under /apps/rn to run the project.

Using the above seems to be the best approach - without trying to hack things together.

@iangregsondev
Copy link

iangregsondev commented Dec 31, 2019

Hi, I thought I would update here, my previous tests were flawed :-(

Multiple package.json was cause for confusion and also the node_modules lives under apps/rn but what about the libs/rn etc ... These would not be able to access them - multiple package.json - was never the right solution :-)

Anyway, I have a working version, I felt compelled to repost here as I didn't want anyone following my example above - that causes issues..

Here is what I have.

  1. my RN native app is under apps/rn
    1a. Copied the .expo and .expo-shared folder to the root (nx)
  2. app.json is in the root (nx) and I have updated the assets icons etc to point to the assets under apps i.e.
    "icon": "./apps/rn/src/assets/icon.png",
    "splash": {
      "image": "./apps/rn/src/assets/splash.png",

Also copied the babel.config.js to the root.

  1. It's important that your root package.json contains the following, it should not cause issues with other apps/libs - well not in my case as I always have esModuleInterop and allowSyntethicDefaultImports set anyway, jsx only applies to react apps. If, for example, you had another app in nx that was a react app you could just override this anyway - considering using react is pretty well supported and it would use the tsconfig in "it's" app directory.
    "jsx": "react-native",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
  1. You need to include a file called App.tsx (yes uppercase A!) in the root, expo has been hardcoded to look for this file - there is a way to override it by providing your own implementation of a js file - but I don't want to introduce issues - you can read about it here
    Remove entrypoint from configuration docs for app.json expo/expo#1034

I just did this, which passes control to my app.tsx (lower case which is generally the default for react and nx - you can choose what you want)

import React from "react"

import App from "./apps/rn/src/app/app"

export default App

So the App.tsx does nothing but call up the chain into where my app is.

  1. I added the scripts to the package.json but prefixed them with expo:
    "expo:start": "expo start",
    "expo:android": "expo start --android",
    "expo:ios": "expo start --ios",
    "expo:web": "expo start --web",
    "expo:eject": "expo eject"

I hope that cleared some things up.

To summarise..

Everything works, no dual package.json or node_modules. There is an App.tsx in the root, either live with it or see the link above to override it.

The app.json is in the root, I believe you can change the name of this and call --config the expo cli, if anyone is worried about it being too much of a generic name.

@vinzcoco
Copy link

vinzcoco commented Jan 6, 2020

Hello,
Very good feature. Have you got a release date for this feature ?
Thank's

@asherccohen
Copy link
Author

There's some good progress on building plugins for Nx.
There isn't much documentation at the time of writing but this can help:
npx create-nx-plugin my-plugin

Anyone interested to use the information in this thread to create a plugin for React Native?
I'll try to give support but time is limited.

@iamyellow
Copy link

iamyellow commented Feb 19, 2020

hey @asherccohen i'm interested. i don't have a lot of time, but eventually i'm going to need it, so why don't get my hands dirty? :) thanks!

@asherccohen
Copy link
Author

@jaysoo is working on supporting react native in nx. We can ask what's the progress and provide our help if he needs.

@jaysoo
Copy link
Member

jaysoo commented Feb 19, 2020

Quick update: The integration is a bit more complicated than what I originally thought because react-native assumes a few things about directory structure, which doesn't play too nicely with how Nx structures apps/libs.

I've put this work on pause for now so focus on other React issues/features, but it is something we definitely want in the future.

Like @asherccohen has mentioned, we are encouraging people to write their own plugins using create-nx-plugin for capabilities missing in core Nx. So definitely keep and eye out on a guide for that -- or jump in now if you're adventurous. :)

@iamyellow
Copy link

i understand @jaysoo i guess you're finding a tone of problems w/ metro bundler. me too. most of my problems were solved with babel-plugin-module-resolver and this:
https://medium.com/@dushyant_db/how-to-import-files-from-outside-of-root-directory-with-react-native-metro-bundler-18207a348427

@jaysoo
Copy link
Member

jaysoo commented Feb 19, 2020

I got to the point where the JS bundle generates, but it wasn't being located by the native app. I saw that some of the build scripts had hard-coded ../../../node_modules/react-native/... and other things like that. Further work requires a step through the native app and see what's happening.

The branch I had is out of date, but maybe I can rebase and push this week if anyone smarter wants to take a look. :)

@iamyellow
Copy link

iamyellow commented Feb 19, 2020 via email

@jaysoo
Copy link
Member

jaysoo commented Feb 19, 2020

@iamyellow I'll link something here in the next few days -- once I have a chance to create the example repo.

@asherccohen
Copy link
Author

@iamyellow I'll link something here in the next few days -- once I have a chance to create the example repo.

Thanks @jaysoo!
Well @iamyellow, we have a team!
@jbuijgers made an awesome work with his external package (maybe wants to join forces) and I fixed most of the internal node_modules linking in the description at the top (just for Android, but could dig in iOS).
My only problem is that I'm new to schematics so I don't know how to configure them.
Let's have a look at the docs for create-nx-plugin too.
Also as a word of caution, the latest react-native guidelines suggest using react-native-cli with npx for most of the commands instead of npm and to NOT install the cli as a global package, more on this can be found on their docs.

@iamyellow
Copy link

sweet! honestly, yesterday was the first time i've read about schematics. i'm amazed... i really love how the js/ts ecosystem is bringing such a cool dev tools to us, the developers. i'll try to dig deeply there as well :)
so, i understand would be understand how create-nx-plugin works with some hello world stuff (honestly, i prefer the by example approach rather than reading docs hehehe).
i'm curious, why are you mentioning that about global vs local installation?

@asherccohen
Copy link
Author

Because I experienced (and detailed above) an issue because of the cli installed as a global package and if that's the standard I would follow it, to help react-native devs in the transition. We should make sure that configs are not too far from a standalone project or it will be confusing.
This is true for other plugins in nx that are somehow different from their vanilla counterpart. Just my opinion.
If you're working on schematics I'll be working on a special config to handle ios certificates/provisioning files automatically!!!

@jaysoo
Copy link
Member

jaysoo commented Feb 24, 2020

@jbuijgers made an awesome work with his external package (maybe wants to join forces) and I fixed most of the internal node_modules linking in the description at the top (just for Android, but could dig in iOS).

@asherccohen @jbuijgers Is this package on public github?

I pushed a rebased branch for the RN integration I was working. I was stuck on getting the dev jsbundle to work in development mode. https://github.com/jaysoo/nx/tree/react-native/packages/react-native/src

My idea was to provide support for the RN CLI commands (e.g. run-ios, run-android, link, etc.) using builders. And we also want to have good support for consuming native libs in the workspace (i.e. be able to create them, compile, and link).

Note: I think it's better to not support Expo initially since I believe most production apps will need to use native libraries at some point--at least that's my experience.

@asherccohen
Copy link
Author

asherccohen commented Feb 24, 2020

@jaysoo Yes the npm package is public https://www.npmjs.com/package/@jbuijgers/nx-react-native
Works for android, but from what I could see there should no issue with iOS.

I agree with you on expo. I would work my way without it for now, giving devs the same ability to work with native modules.

Link command is not needed anymore as react-native supports auto-linking with jetifier. Package maintainers should make changes to their repos, also considering that a package that doesn't support auto-linking might not support androidX either, so better avoid them.

I also suggest we look into the global react-native-cli issue, see my comment above.

I'll see if I can get the time to check your repo.tx

@asherccohen
Copy link
Author

Hey, did anyone in this thread had the time to carry on work on this? @jaysoo @iamyellow @iangregsondev @jbuijgers

@jbuijgers
Copy link

Sorry, I've been quite busy for the past months and will have little time to work on this. If anyone is interested in taking the lead, I would very much be interested to participate where I can.

@iangregsondev
Copy link

@asherccohen My tests were with expo, I wasn't really using bulders. I kind of got it working but I haven't really taken it any further as I am also very interested in a NON-expo react native :-)

So I am also eager to see any results with regards to getting the builders working with standard react native

@jaysoo
Copy link
Member

jaysoo commented Apr 3, 2020

I think we may refocus on React Native maybe close to the summer (May/June?). We're working on polishing some of the existing features and fixing issues.

@Lampent
Copy link

Lampent commented Apr 29, 2020

I think we may refocus on React Native maybe close to the summer (May/June?). We're working on polishing some of the existing features and fixing issues.

It would be amazing.

@adamjamesturner93
Copy link

@jaysoo do you still think RN will be coming May/June time? If so I will delay a personal project a little while! :)

@asherccohen
Copy link
Author

I'm investigating the @expo/next-adapter to verify if an hybrid solution with Expo/next is possible. I'm still unsure how to write nx builders, so any help with that is much appreciated.

@TimNuman
Copy link

Any news on this?

@asherccohen
Copy link
Author

Well currently I'm trying the expo way as it looks promising. Since we already have next.js support we can work on that and bootstrap an hybrid expo solution.

Same problem as above, I have no understanding of schematics and builders so any help is appreciated.

@TimNuman
Copy link

Same problem as above, I have no understanding of schematics and builders so any help is appreciated.

Me neither..

@jaysoo
Copy link
Member

jaysoo commented Jul 22, 2020

@asherccohen Feel free to reach out to me on Slack if you need any help. https://nrwlcommunity.slack.com

@cheunjm
Copy link

cheunjm commented Sep 8, 2020

Any updates on this plugin?

@denniske
Copy link

denniske commented Sep 18, 2020

I have just setup a project like @iangregsondev described:
denniske/nx-expo-project

The expo app is in /apps/companion. Also I have a library in /libs/data.
The expo app works fine when I don't import anything from data using npm i && npm start in the root folder.

But when I try to import something from @nex/data the following error occurs:

Failed building JavaScript bundle.
Unable to resolve "@nex/data" from "apps/companion/screens/TabOneScreen.tsx"

Does anybody know how to solve this?

Update: I fixed it by adding the following babel.config.js:

module.exports = function(api) {
  api.cache(true);
  return {
    presets: ['babel-preset-expo'],
    plugins: [
      [
        "module-resolver",
        {
          alias: {
            "@nex/data": ["./libs/data/src/index.ts"],
          }
        }
      ]
    ]
  };
};

@jbuijgers
Copy link

@denniske In case you still have some problems with getting imports to work, I remember the Metro config also plays a role in this, you could take a look at this metro.config.js file. Although not 100% sure anymore, it has been a while since I've written the code.

@jaysoo
Copy link
Member

jaysoo commented Sep 22, 2020

We have the react-native plugin in a separate repo. https://github.com/nrwl/nx-react-native

It is not ready yet, but we are working to get it out later this year.

@jaysoo
Copy link
Member

jaysoo commented Sep 22, 2020

Closing this issue since we should be tracking react-native in the other repo now.

@jaysoo jaysoo closed this as completed Sep 22, 2020
@JacopoPatroclo
Copy link

I've used as an example https://github.com/nrwl/nx-react-native to create a plugin for Expo managed workflow.

The repo is here https://github.com/JacopoPatroclo/nx-react-native-expo

I don't know if there are any issues with the way I setup everything (mostly borrowing from nx-react-native) so feel free to open issues if something need to be fixed.

@cdanyl
Copy link

cdanyl commented Oct 30, 2020

@denniske thank you for your setup! I've used for a monorepo project, include NestJS, NextJS and Expo Web, and it work perfectly fine (serve, build and tests).
I change some config files to be able to run all tests including unsupported NX app like Expo.

The repo is here https://github.com/cdanyl/nx-expo-nestjs-nextjs

And like @JacopoPatroclo I don't know if there are any issues. Feel free to open issues if something need to be fixed.

@hudzenko
Copy link

hudzenko commented Oct 8, 2021

Hey guys, thanks a lot for your examples of nx with Expo. It helped for me to have an idea how to use them together.

It will be awesome in case at some point Nx introduces Expo plugin.

Here is my example with nrwl react and expo (beta to have react 17 and be compatible with nrwl react):
https://github.com/hudzenko/nx-expo-and-web

My workaround is running expo app just out of mobile app folder to avoid tslint and babel conflicts / mixing. I am not sure it is good solution and I almost was not testing it, but for me start, test, lint and code sharing works fine.

Additional package.json inside mobile app is smth I saw in app generated by @nrwl/react-native, maybe it is not really necessary here because anyway I run expo commands with help of @nrwl/workspace:run-commands with setting "cwd": "apps/mobile", but I decided to keep it for convenience so it is visible which exactly libs are needed for mobile app

@cvramirez-nasa
Copy link

Hey guys, thanks a lot for your examples of nx with Expo. It helped for me to have an idea how to use them together.

It will be awesome in case at some point Nx introduces Expo plugin.

@hudzenko , in case you haven't seen this expo plugin: https://github.com/JacopoPatroclo/nx-react-native-expo

I used it to create a small proof-of-concept app, and it worked well.

I think there is interest in official support from nx too: JacopoPatroclo/nx-react-native-expo#20

@asherccohen
Copy link
Author

asherccohen commented Oct 28, 2021 via email

@hudzenko
Copy link

hudzenko commented Nov 5, 2021

@cvramirez-nasa Am I able to use latest Expo/React-Native/React with that plugin?
We are starting long term project with react and react native apps and we need an ability of being able to update dependencies when expo sdk and nx react plugins are updated

@hudzenko
Copy link

hudzenko commented Nov 5, 2021

I am super interested in official support, but project can not wait anymore

@github-actions
Copy link

This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated scope: react Issues related to React support for Nx type: feature
Projects
None yet
Development

No branches or pull requests