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-macos-init for adding macOS apps to existing react-native init projects. #291

Merged
merged 9 commits into from
Apr 2, 2020

Conversation

tom-un
Copy link
Collaborator

@tom-un tom-un commented Apr 1, 2020

Please select one of the following

  • I am removing an existing difference between facebook/react-native and microsoft/react-native 👍
  • I am cherry-picking a change from Facebook's react-native into microsoft/react-native 👍
  • I am making a fix / change for the macOS implementation of react-native
  • I am making a change required for Microsoft usage of react-native

This change adds a new subpackage react-native-macos-init which adds a macOS application and dependencies to an existing project that was created by npx react-native init. It adds to the local-cli a local-cli/generate-macos.js script which is invoked by react-native-macos-init to perform the creation of a macOS Xcode project based on template files. The react-native-macos-init script will also add react-native-macos as a dependency in the project's package.json, add a start:macos script helper, and add necessary react-native.config.js and metro.config.macos.js files to the project.

The new macOS app created hosts the existing react-native JavaScript App that was generated by npx react-native init. This sample app was designed to run on core iOS and Android and used some components such as StatusBar that were broken in the react-native-macos fork. So this change also adds macos to core parity of several components: AccessibilityInfo, MaskedViewIOS, Picker, SegmentedControlIOS, StatusBar. Similarly, it expands the parity in the RNTester app. Finally, react-native init apps use a NewAppScreen component. The component in core has conditional language for iOS and Android. In the fork additional language was added for macOS.

The react-native-macos-init package is based on the react-native-windows-init package, and the local-cli scripts are based on the react-native-windows/vnext/local-cli.

The macOS Xcode project templates are based off of the exiting iOS Xcode project template in core, but it drops the -tvOS targets and schemes and adds -macOS targets, schemes, and supporting native source files.

This change does not yet change to build pipeline to publish the new react-native-macos-init package to npmjs.org. A follow-up PR will update the build pipeline to have a CI test and npm publish.

This change does not extend the local-cli beyond the addition of the generate-macos.js script. Follow-up PR's will add a run-macos command similar to the run and run-android commands in core and the run-windows command in react-native-windows.

Focus areas to test

Testing of this change was performed using a local copy of this branch, Verdaccio to run a local npm proxy, and react-native-macos and react-native-macos-init were published to the local Verdaccio server. Then the intended usage was tested:

$ npx react-native init AwesomeApp
$ cd AwesomeApp
$ npx react-native-macos-init

to create the macOS app and install the dependencies. Then to test the app:

$ open macos/AwesomeApp.xcodeproj
$ yarn start:macos

and in Xcode the AwesomeApp-macOS target was chosen and Run.

init

Microsoft Reviewers: Open in CodeFlow

@tom-un tom-un merged commit ef31e51 into microsoft:master Apr 2, 2020

## Usage

Run this from an existing `react-native` project to install `react-native-macos` and generate initial project files for macOS.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this doc make note of the RN version to use? I.e. that it only supports apps that use RN v0.60.0 atm?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script will attempt to pick the latest version of react-native-macos whose version number matches the version of react-native currently installed in the init'd project. Same as in react-native-windows-init. Does it need to enumerate versions in the readme? (they'll always be changing)


Example usage
```
$ npx react-native init AwesomeProject
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And re the above comment, should this then be amended to the following?

npx react-native init AwesomeProject --version=0.60.0

@alloy
Copy link
Member

alloy commented Apr 2, 2020

I’ll make a PR for the above comments. #292

I was also wondering about the choice to install the template into ./macos, whereas the project will actually contain iOS and macOS targets. Do you still want to go forward with also including the iOS target in this template? I like that they are in the same part of the project tree, but I worry that this will lead to:

  • The overhead of needing to keep the iOS template up-to-date with upstream.
  • Requiring the dev to move all their existing files over from ./ios if they decide to add a ./macos target later on.

@tom-un
Copy link
Collaborator Author

tom-un commented Apr 2, 2020

I’ll make a PR for the above comments. #292

I was also wondering about the choice to install the template into ./macos, whereas the project will actually contain iOS and macOS targets. Do you still want to go forward with also including the iOS target in this template? I like that they are in the same part of the project tree, but I worry that this will lead to:

  • The overhead of needing to keep the iOS template up-to-date with upstream.
  • Requiring the dev to move all their existing files over from ./ios if they decide to add a ./macos target later on.

The way the xcodeproj is emitted the target repo actualy ends up with two ios targets: the existing one created by react-native int and dependent on core, and a second one in the macos project dependent on the microsoft fork. I did it this way out of the experience of maintaining test apps for macOS components with native modules both inside microsoft and now in react-native-community. When developing native Apple apps including NativeModules that share source code between mac and iOS its very convenient to have both targets in the same app so that you can build both targets and run to ensure a change for mac hasn't broken iOS. Its even more important since the fork requires a special instance of metro running with command line arguments target the react-native fork instead of core (if the ios and macos targets were separate project one would have to shutdown and restart the bundler when switching between projects). The seperate bundler issue is being worked on. But I don't think its possible to have a single xcodeproj that would alternatively take a dependency on two seperate copies of React xcodeprojs. To illustrate, this is the current layout with dependencies:

AwesomeProject
  node_modules
    react-native-macos
      React       <---------------+
    react-native                  |
      React       <-----------+   |
  ios                         |   |
    AwesomeProject.xcodeproj -+   |
      AwesomeProject (ios)        |
      AwesomeProject-tvOS         |
  macos                           |
    AwesomeProject.xcodeproj -----+
      AwesomeProject (ios fork)
      AwesomeProject-macOS

If there was a single apple/AwesomeProject.xcodeproj i don't think it can consume the two sets of React projects from the two version of react-native* in node_modules. It gets even messier in the react-native-community projects where there are two more sets of xcodeproj's for the NativeModules provided by the component. Maybe if the projects in the Microsoft fork were uniquely named as not to collide with core? Like React-macos instead of React, RCTText-macos instead of RCTText, etc.?

@thymikee
Copy link

thymikee commented Apr 2, 2020

Awesome seeing some work in this space :) Anything preventing this to be a template using regular init approach?

npx react-native init MyApp --template react-native-macos

That would require react-native-macos (or relevant) to be published to npm and contain template.config.js file with configuration: https://github.com/react-native-community/cli/blob/master/docs/init.md#creating-custom-template. The RN CLI would copy over the files from templateDir defined in said config to the MyApp dir.

@acoates-ms
Copy link
Collaborator

@thymikee that approach gets complex with a matrix of platforms. What if you want windows and macos... and tvos?

Having said that, I do think we will eventually want to do some tighter integration with the CLI. -- We may try to have it ask what platforms you want when you init a new project or something. But it gets complex when you need to work out what version of RN the different platforms support.

@thymikee
Copy link

thymikee commented Apr 3, 2020

One could create a repository (or many repositories) with all of those set up (like this one for web+android+ios https://github.com/brunolemos/react-native-web-monorepo).

We consciously followed this path (copy-paste template without "magic"), to move complexity from the CLI to template/platform maintainers and make CLI platform agnostic. You can download any template version you like as well with:

init --template react-native-web-monorepo@^x.x.x

Not saying this is ideal, but it's the best we came up with having future maintainability of the CLI in mind.

@alloy
Copy link
Member

alloy commented Apr 3, 2020

@thymikee I think it’s good to realise that in the short-term we are trying to allow users to target upstream RN for their ios product and our fork for the macos target, which is why this current approach augments the existing upstream template.

Like @acoates-ms said, though, in the long-run we’ll most likely change this. I can imagine other things along this theme of platforms changing anyways when, for instance, this proposal gets adopted react-native-community/discussions-and-proposals#182 (comment)

@orta
Copy link

orta commented Apr 7, 2020

coooooooool

@tom-un tom-un deleted the tomun/react-native-macos-init branch May 8, 2020 21:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants