From 26ec042ba5873971175a445af26c0b98089c44f5 Mon Sep 17 00:00:00 2001 From: Emily Xiong Date: Wed, 5 Jul 2023 12:40:37 -0400 Subject: [PATCH] feat(react-native): upgrade react-native to 0.72 --- .../packages/expo/documents/overview.md | 6 +- .../packages/expo/executors/build.json | 3 +- .../packages/expo/executors/run.json | 1 + .../packages/expo/executors/start.json | 1 + .../react-native/executors/build-android.json | 20 +- .../react-native/executors/build-ios.json | 16 +- .../react-native/executors/pod-install.json | 12 +- .../react-native/executors/run-android.json | 12 +- .../react-native/executors/run-ios.json | 15 +- docs/shared/packages/expo/expo-plugin.md | 6 +- e2e/expo/src/expo.test.ts | 8 +- package.json | 3 +- .../application/application.spec.ts | 12 - .../files/app/.detoxrc.json.template | 18 - .../application/lib/get-targets.spec.ts | 11 +- .../generators/application/lib/get-targets.ts | 11 +- packages/expo/migrations.json | 73 ++ packages/expo/package.json | 7 +- packages/expo/plugins/with-nx-metro.ts | 34 +- .../executors/build-list/build-list.impl.ts | 6 +- .../expo/src/executors/build/build.impl.ts | 17 +- packages/expo/src/executors/build/schema.json | 3 +- .../src/executors/download/download.impl.ts | 1 + .../expo/src/executors/export/export.impl.ts | 8 +- .../src/executors/install/install.impl.ts | 3 +- .../src/executors/prebuild/prebuild.impl.ts | 4 +- packages/expo/src/executors/run/run.impl.ts | 21 +- packages/expo/src/executors/run/schema.d.ts | 3 + packages/expo/src/executors/run/schema.json | 1 + packages/expo/src/executors/start/schema.d.ts | 4 +- packages/expo/src/executors/start/schema.json | 1 + .../expo/src/executors/start/start.impl.ts | 23 +- .../expo/src/executors/submit/submit.impl.ts | 9 +- .../expo/src/executors/update/update.impl.ts | 6 +- .../application/application.spec.ts | 36 - .../files/metro.config.js.template | 52 +- .../application/files/package.json.template | 1 + .../generators/application/lib/add-project.ts | 8 + .../update-16-6-0/add-depends-on.ts | 21 + .../update-16-6-0/update-metro-config.ts | 58 + packages/expo/src/utils/versions.ts | 27 +- packages/react-native/migrations.json | 78 ++ packages/react-native/package.json | 5 +- .../react-native/plugins/with-nx-metro.ts | 33 +- .../build-android/build-android.impl.ts | 69 +- .../src/executors/build-android/schema.d.ts | 8 +- .../src/executors/build-android/schema.json | 22 +- .../src/executors/build-ios/build-ios.impl.ts | 88 +- .../src/executors/build-ios/schema.d.ts | 3 + .../src/executors/build-ios/schema.json | 14 +- .../src/executors/bundle/bundle.impl.ts | 45 +- .../executors/pod-install/pod-install.impl.ts | 2 +- .../src/executors/pod-install/schema.d.ts | 4 +- .../src/executors/pod-install/schema.json | 12 +- .../executors/run-android/run-android.impl.ts | 84 +- .../src/executors/run-android/schema.json | 14 +- .../src/executors/run-ios/run-ios.impl.ts | 96 +- .../src/executors/run-ios/schema.json | 13 +- .../src/executors/start/start.impl.ts | 76 +- .../src/generators/application/application.ts | 6 - .../application/files/app/.ruby-version | 1 - .../application/files/app/Gemfile.template | 4 +- .../app/android/app/build.gradle.template | 51 +- .../MainActivity.java.template | 7 +- .../res/drawable/rn_edit_text_material.xml | 2 +- .../files/app/android/build.gradle.template | 2 +- .../files/app/android/gradle.properties | 2 +- .../android/gradle/wrapper/gradle-wrapper.jar | Bin 59821 -> 61574 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- .../application/files/app/android/gradlew.bat | 15 +- .../files/app/android/gradlew.template | 18 +- .../app/android/settings.gradle.template | 3 +- .../files/app/ios/Podfile.template | 14 +- .../project.pbxproj.template | 8 +- .../ios/__className__/AppDelegate.mm.template | 10 - .../files/app/metro.config.js.template | 67 +- .../files/app/package.json.template | 1 + .../generators/application/lib/add-project.ts | 7 + .../react-native/src/generators/init/init.ts | 4 +- ...age.json__tmpl__ => package.json.template} | 0 .../{index.ts__tmpl__ => index.ts.template} | 0 ...ig.json__tmpl__ => tsconfig.json.template} | 0 ...son__tmpl__ => tsconfig.lib.json.template} | 0 .../src/generators/library/library.ts | 1 - .../update-16-6-0/add-depends-on.ts | 39 + .../update-16-6-0/update-metro-config.ts | 56 + .../react-native/src/utils/get-cli-options.ts | 4 +- .../src/utils/pod-install-task.ts | 38 +- packages/react-native/src/utils/versions.ts | 19 +- pnpm-lock.yaml | 1019 ++++++++++++----- 90 files changed, 1646 insertions(+), 1003 deletions(-) create mode 100644 packages/expo/src/migrations/update-16-6-0/add-depends-on.ts create mode 100644 packages/expo/src/migrations/update-16-6-0/update-metro-config.ts delete mode 100644 packages/react-native/src/generators/application/files/app/.ruby-version rename packages/react-native/src/generators/library/files/lib/{package.json__tmpl__ => package.json.template} (100%) rename packages/react-native/src/generators/library/files/lib/src/{index.ts__tmpl__ => index.ts.template} (100%) rename packages/react-native/src/generators/library/files/lib/{tsconfig.json__tmpl__ => tsconfig.json.template} (100%) rename packages/react-native/src/generators/library/files/lib/{tsconfig.lib.json__tmpl__ => tsconfig.lib.json.template} (100%) create mode 100644 packages/react-native/src/migrations/update-16-6-0/add-depends-on.ts create mode 100644 packages/react-native/src/migrations/update-16-6-0/update-metro-config.ts diff --git a/docs/generated/packages/expo/documents/overview.md b/docs/generated/packages/expo/documents/overview.md index 2bd30826833767..59d31ad0202b63 100644 --- a/docs/generated/packages/expo/documents/overview.md +++ b/docs/generated/packages/expo/documents/overview.md @@ -50,7 +50,7 @@ nx start my-app To generate a new library run: ```shell -npx nx g @nx/react-native:lib your-lib-name +npx nx g @nx/expo:lib your-lib-name ``` ### Generating Components @@ -58,7 +58,7 @@ npx nx g @nx/react-native:lib your-lib-name To generate a new component inside library run: ```shell -npx nx g @nx/react-native:component your-component-name --project=your-lib-name --export +npx nx g @nx/expo:component your-component-name --project=your-lib-name --export ``` Replace `your-lib-name` with the app's name as defined in your `tsconfig.base.json` file or the `name` property of your `package.json` @@ -269,6 +269,8 @@ Below table is a map between expo commands and Nx commands: | `expo install` | `nx install ` | | `eas build` | `nx build ` | | `eas build:list` | `nx build-list ` | +| `eas update` | `nx update ` | +| `eas submit` | `nx submit ` | ## More Documentation diff --git a/docs/generated/packages/expo/executors/build.json b/docs/generated/packages/expo/executors/build.json index c1bc9395e445f3..7d5fc37afc68f8 100644 --- a/docs/generated/packages/expo/executors/build.json +++ b/docs/generated/packages/expo/executors/build.json @@ -46,7 +46,8 @@ }, "output": { "type": "string", - "description": "Output path for local build" + "description": "Output path for local build", + "examples": ["../../dist/MyApp.tar.gz", "../../dist"] }, "wait": { "type": "boolean", diff --git a/docs/generated/packages/expo/executors/run.json b/docs/generated/packages/expo/executors/run.json index 668255c4e7e2f4..2e93f59d43d55f 100644 --- a/docs/generated/packages/expo/executors/run.json +++ b/docs/generated/packages/expo/executors/run.json @@ -42,6 +42,7 @@ "type": "boolean", "description": "Syncs npm dependencies to package.json (for React Native autolink).", "default": true, + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "x-priority": "internal" }, "port": { diff --git a/docs/generated/packages/expo/executors/start.json b/docs/generated/packages/expo/executors/start.json index 5a1de553705ec0..681aa875edc0e4 100644 --- a/docs/generated/packages/expo/executors/start.json +++ b/docs/generated/packages/expo/executors/start.json @@ -88,6 +88,7 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to package.json (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "default": true } }, diff --git a/docs/generated/packages/react-native/executors/build-android.json b/docs/generated/packages/react-native/executors/build-android.json index cdac5b307debcd..565bd793d24a0b 100644 --- a/docs/generated/packages/react-native/executors/build-android.json +++ b/docs/generated/packages/react-native/executors/build-android.json @@ -45,7 +45,8 @@ "packager": { "type": "boolean", "description": "Launch packager while building", - "default": true + "default": true, + "x-deprecated": "Run `nx run :start` instead. Will be removed in Nx 17." }, "port": { "type": "number", @@ -53,8 +54,10 @@ "default": 8081 }, "tasks": { - "type": "array", - "items": { "type": "string" }, + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Run custom Gradle tasks. By default it's \"assembleDebug\". Will override passed mode and variant arguments.", "examples": [ "assembleDebug", @@ -71,8 +74,12 @@ "default": false }, "extraParams": { - "type": "string", - "description": "Custom params passed to gradle build command" + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], + "description": "Custom params passed to gradle build command", + "examples": ["-x lint -x test"] }, "interactive": { "type": "boolean", @@ -81,7 +88,8 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", - "default": true + "default": true, + "x-deprecated": "Add sync-deps to dependsOn instead" }, "resetCache": { "type": "boolean", diff --git a/docs/generated/packages/react-native/executors/build-ios.json b/docs/generated/packages/react-native/executors/build-ios.json index 9f1d67083d6010..861bd13c035396 100644 --- a/docs/generated/packages/react-native/executors/build-ios.json +++ b/docs/generated/packages/react-native/executors/build-ios.json @@ -11,11 +11,7 @@ "presets": [ { "name": "Build iOS for a simulator", "keys": ["simulator"] }, { "name": "Build iOS for a device", "keys": ["device"] }, - { "name": "Build iOS for a device with udid", "keys": ["udid"] }, - { - "name": "Run `pod install` before building iOS app", - "keys": ["install"] - } + { "name": "Build iOS for a device with udid", "keys": ["udid"] } ], "properties": { "simulator": { @@ -72,17 +68,22 @@ "description": "Explicitly select which scheme and configuration to use before running a build" }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params that will be passed to xcodebuild command." }, "install": { "type": "boolean", "description": "Runs `pod install` for native modules before building iOS app.", + "x-deprecated": "Add pod-install to dependsOn in project.json for this target instead", "default": true }, "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "default": true }, "resetCache": { @@ -93,7 +94,8 @@ "packager": { "type": "boolean", "description": "Launch packager while building", - "default": true + "default": true, + "x-deprecated": "Run `nx run :start` instead. Will be removed in Nx 17." } }, "required": [], diff --git a/docs/generated/packages/react-native/executors/pod-install.json b/docs/generated/packages/react-native/executors/pod-install.json index da7c4b7f32ed18..2e4f9beae68472 100644 --- a/docs/generated/packages/react-native/executors/pod-install.json +++ b/docs/generated/packages/react-native/executors/pod-install.json @@ -12,9 +12,19 @@ "type": "object", "properties": { "buildFolder": { - "description": "Location for iOS build artifacts. Corresponds to Xcode's \"-derivedDataPath\". Relative to ios directory", + "description": "Location for iOS build artifacts. Corresponds to Xcode's \"-derivedDataPath\". Relative to ios directory.", "type": "string", "default": "./build" + }, + "repoUpdate": { + "description": "Force running `pod repo update` before install.", + "type": "boolean", + "default": false + }, + "deployment": { + "description": "Disallow any changes to the Podfile or the Podfile.lock during installation.", + "type": "boolean", + "default": false } }, "required": ["buildFolder"], diff --git a/docs/generated/packages/react-native/executors/run-android.json b/docs/generated/packages/react-native/executors/run-android.json index 1f64e92ced64d8..cf0a67aa56360a 100644 --- a/docs/generated/packages/react-native/executors/run-android.json +++ b/docs/generated/packages/react-native/executors/run-android.json @@ -77,8 +77,10 @@ "default": 8081 }, "tasks": { - "type": "array", - "items": { "type": "string" }, + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Run custom Gradle tasks. By default it's \"assembleDebug\". Will override passed mode and variant arguments.", "examples": [ "assembleDebug", @@ -95,7 +97,10 @@ "default": false }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params passed to gradle build command" }, "interactive": { @@ -105,6 +110,7 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn for this target in project.json instead", "default": true }, "resetCache": { diff --git a/docs/generated/packages/react-native/executors/run-ios.json b/docs/generated/packages/react-native/executors/run-ios.json index 58f619d5169ac2..387f44a2b52c15 100644 --- a/docs/generated/packages/react-native/executors/run-ios.json +++ b/docs/generated/packages/react-native/executors/run-ios.json @@ -13,11 +13,7 @@ "presets": [ { "name": "Run iOS on a simulator", "keys": ["simulator"] }, { "name": "Run iOS on a device", "keys": ["device"] }, - { "name": "Run iOS on a device with udid", "keys": ["udid"] }, - { - "name": "Run `pod install` before building iOS app", - "keys": ["install"] - } + { "name": "Run iOS on a device with udid", "keys": ["udid"] } ], "properties": { "xcodeConfiguration": { @@ -81,17 +77,22 @@ "description": "Explicitly select which scheme and configuration to use before running a build" }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params that will be passed to xcodebuild command." }, "install": { "type": "boolean", "description": "Runs `pod install` for native modules before building iOS app.", - "default": true + "default": true, + "x-deprecated": "Add `pod-install` to dependsOn for this target in project.json instead." }, "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add `sync-deps` to dependsOn for this target in project.json instead.", "default": true }, "resetCache": { diff --git a/docs/shared/packages/expo/expo-plugin.md b/docs/shared/packages/expo/expo-plugin.md index 2bd30826833767..59d31ad0202b63 100644 --- a/docs/shared/packages/expo/expo-plugin.md +++ b/docs/shared/packages/expo/expo-plugin.md @@ -50,7 +50,7 @@ nx start my-app To generate a new library run: ```shell -npx nx g @nx/react-native:lib your-lib-name +npx nx g @nx/expo:lib your-lib-name ``` ### Generating Components @@ -58,7 +58,7 @@ npx nx g @nx/react-native:lib your-lib-name To generate a new component inside library run: ```shell -npx nx g @nx/react-native:component your-component-name --project=your-lib-name --export +npx nx g @nx/expo:component your-component-name --project=your-lib-name --export ``` Replace `your-lib-name` with the app's name as defined in your `tsconfig.base.json` file or the `name` property of your `package.json` @@ -269,6 +269,8 @@ Below table is a map between expo commands and Nx commands: | `expo install` | `nx install ` | | `eas build` | `nx build ` | | `eas build:list` | `nx build-list ` | +| `eas update` | `nx update ` | +| `eas submit` | `nx submit ` | ## More Documentation diff --git a/e2e/expo/src/expo.test.ts b/e2e/expo/src/expo.test.ts index 139fb29b112fff..28ef3fe4f704d1 100644 --- a/e2e/expo/src/expo.test.ts +++ b/e2e/expo/src/expo.test.ts @@ -92,15 +92,15 @@ describe('expo', () => { expect(prebuildResult.combinedOutput).toContain('Config synced'); }); - // TODO(emily): expo-cli always fetches the latest version of react native - // re-enable it when expo-cli is fixed + // TODO(emily): this test failed due to version conflict with conflict with @config-plugins/detox + // https://github.com/expo/config-plugins/issues/178 xit('should install', async () => { // run install command const installResults = await runCLIAsync( - `install ${appName} --no-interactive --check` + `install ${appName} --no-interactive` ); expect(installResults.combinedOutput).toContain( - 'Dependencies are up to date' + 'Successfully ran target install' ); }); diff --git a/package.json b/package.json index 8185fee050a58a..b1047d269388aa 100644 --- a/package.json +++ b/package.json @@ -204,7 +204,8 @@ "magic-string": "~0.26.2", "markdown-factory": "^0.0.6", "memfs": "^3.0.1", - "metro-resolver": "^0.74.1", + "metro-config": "0.76.7", + "metro-resolver": "0.76.7", "mini-css-extract-plugin": "~2.4.7", "minimatch": "3.0.5", "next-sitemap": "^3.1.10", diff --git a/packages/detox/src/generators/application/application.spec.ts b/packages/detox/src/generators/application/application.spec.ts index ef4ff058914a52..08e5f556b14ffd 100644 --- a/packages/detox/src/generators/application/application.spec.ts +++ b/packages/detox/src/generators/application/application.spec.ts @@ -342,12 +342,6 @@ describe('detox application generator', () => { 'cd ../../../my-dir/my-app/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug', type: 'android.apk', }, - 'android.eas': { - binaryPath: '../../../my-dir/my-app/dist/MyDirMyApp.apk', - build: - 'npx nx run my-dir-my-app:download --platform android --distribution simulator --output=../../../my-dir/my-app/dist/', - type: 'android.apk', - }, 'android.local': { binaryPath: '../../../my-dir/my-app/dist/MyDirMyApp.apk', build: @@ -368,12 +362,6 @@ describe('detox application generator', () => { "cd ../../../my-dir/my-app/ios && xcodebuild -workspace MyDirMyApp.xcworkspace -scheme MyDirMyApp -configuration Debug -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -derivedDataPath ./build -quiet", type: 'ios.app', }, - 'ios.eas': { - binaryPath: '../../../my-dir/my-app/dist/MyDirMyApp.app', - build: - 'npx nx run my-dir-my-app:download --platform ios --distribution simulator --output=../../../my-dir/my-app/dist/', - type: 'ios.app', - }, 'ios.local': { binaryPath: '../../../my-dir/my-app/dist/MyDirMyApp.app', build: diff --git a/packages/detox/src/generators/application/files/app/.detoxrc.json.template b/packages/detox/src/generators/application/files/app/.detoxrc.json.template index 32023673a5f2ed..622d7e779da76e 100644 --- a/packages/detox/src/generators/application/files/app/.detoxrc.json.template +++ b/packages/detox/src/generators/application/files/app/.detoxrc.json.template @@ -20,11 +20,6 @@ "binaryPath": "<%= offsetFromRoot %><%= appRoot %>/ios/build/Build/Products/Release-iphonesimulator/<%= appClassName %>.app" }, <% if (framework === 'expo') { %> - "ios.eas": { - "type": "ios.app", - "build": "<%= exec %> nx run <%= appFileName %>:download --platform ios --distribution simulator --output=<%= offsetFromRoot %><%= appRoot %>/dist/", - "binaryPath": "<%= offsetFromRoot %><%= appRoot %>/dist/<%= appExpoName %>.app" - }, "ios.local": { "type": "ios.app", "build": "<%= exec %> nx run <%= appFileName %>:build --platform ios --profile preview --wait --local --no-interactive --output=<%= offsetFromRoot %><%= appRoot %>/dist/<%= appExpoName %>.tar.gz", @@ -42,11 +37,6 @@ "binaryPath": "<%= offsetFromRoot %><%= appRoot %>/android/app/build/outputs/apk/release/app-release.apk" }, <% if (framework === 'expo') { %> - "android.eas": { - "type": "android.apk", - "build": "<%= exec %> nx run <%= appFileName %>:download --platform android --distribution simulator --output=<%= offsetFromRoot %><%= appRoot %>/dist/", - "binaryPath": "<%= offsetFromRoot %><%= appRoot %>/dist/<%= appExpoName %>.apk" - }, "android.local": { "type": "android.apk", "build": "<%= exec %> nx run <%= appFileName %>:build --platform android --profile preview --wait --local --no-interactive --output=<%= offsetFromRoot %><%= appRoot %>/dist/<%= appExpoName %>.apk", @@ -78,10 +68,6 @@ "app": "ios.debug" }, <% if (framework === 'expo') { %> - "ios.sim.eas": { - "device": "simulator", - "app": "ios.eas" - }, "ios.sim.local": { "device": "simulator", "app": "ios.local" @@ -96,10 +82,6 @@ "app": "android.debug" }, <% if (framework === 'expo') { %> - "android.emu.eas": { - "device": "emulator", - "app": "android.eas" - }, "android.emu.local": { "device": "emulator", "app": "android.local" diff --git a/packages/detox/src/generators/application/lib/get-targets.spec.ts b/packages/detox/src/generators/application/lib/get-targets.spec.ts index 4ffddd609da9ae..07730d357bf836 100644 --- a/packages/detox/src/generators/application/lib/get-targets.spec.ts +++ b/packages/detox/src/generators/application/lib/get-targets.spec.ts @@ -4,14 +4,10 @@ describe('getTargets', () => { it('should return ios test target for expo projects', () => { expect(expoTestTarget('ios.sim', 'test')).toEqual({ options: { - detoxConfiguration: 'ios.sim.eas', + detoxConfiguration: 'ios.sim.local', buildTarget: 'test:build-ios', }, configurations: { - local: { - detoxConfiguration: 'ios.sim.local', - buildTarget: 'test:build-ios:local', - }, bare: { detoxConfiguration: 'ios.sim.debug', buildTarget: 'test:build-ios:bare', @@ -27,12 +23,9 @@ describe('getTargets', () => { it('should return ios build target for expo projects', () => { expect(expoBuildTarget('ios.sim')).toEqual({ options: { - detoxConfiguration: 'ios.sim.eas', + detoxConfiguration: 'ios.sim.local', }, configurations: { - local: { - detoxConfiguration: 'ios.sim.local', - }, bare: { detoxConfiguration: 'ios.sim.debug', }, diff --git a/packages/detox/src/generators/application/lib/get-targets.ts b/packages/detox/src/generators/application/lib/get-targets.ts index b2bee0d29063d8..b1cbfc4aa0f002 100644 --- a/packages/detox/src/generators/application/lib/get-targets.ts +++ b/packages/detox/src/generators/application/lib/get-targets.ts @@ -14,12 +14,9 @@ export function reactNativeBuildTarget(platform: 'ios.sim' | 'android.emu') { export function expoBuildTarget(platform: 'ios.sim' | 'android.emu') { return { options: { - detoxConfiguration: `${platform}.eas`, + detoxConfiguration: `${platform}.local`, }, configurations: { - local: { - detoxConfiguration: `${platform}.local`, - }, bare: { detoxConfiguration: `${platform}.debug`, }, @@ -58,14 +55,10 @@ export function expoTestTarget( return { options: { - detoxConfiguration: `${platform}.eas`, + detoxConfiguration: `${platform}.local`, buildTarget: `${e2eName}:build-${buildPlatform}`, }, configurations: { - local: { - detoxConfiguration: `${platform}.local`, - buildTarget: `${e2eName}:build-${buildPlatform}:local`, - }, bare: { detoxConfiguration: `${platform}.debug`, buildTarget: `${e2eName}:build-${buildPlatform}:bare`, diff --git a/packages/expo/migrations.json b/packages/expo/migrations.json index 1dfe1357644241..14d37ee0b642b1 100644 --- a/packages/expo/migrations.json +++ b/packages/expo/migrations.json @@ -65,6 +65,18 @@ "cli": "nx", "description": "Add app.json for detox", "factory": "./src/migrations/update-16-1-4/add-detox-app-json" + }, + "update-16-6-0-add-dependsOn": { + "cli": "nx", + "version": "16.6.0-beta.0", + "description": "Add dependsOn like ensure-symlink or sync-deps to targets", + "implementation": "./src/migrations/update-16-6-0/add-depends-on" + }, + "update-16-6-0-update-metro-config": { + "cli": "nx", + "version": "16.6.0-beta.0", + "description": "Update metro.config.js to use the new metro config format", + "implementation": "./src/migrations/update-16-6-0/update-metro-config" } }, "packageJsonUpdates": { @@ -855,6 +867,67 @@ "alwaysAddToPackageJson": false } } + }, + "16.6.0": { + "version": "16.6.0-beta.0", + "packages": { + "expo": { + "version": "^49.0.3", + "alwaysAddToPackageJson": false + }, + "@expo/metro-config": { + "version": "~0.10.6", + "alwaysAddToPackageJson": false + }, + "expo-splash-screen": { + "version": "~0.20.4", + "alwaysAddToPackageJson": false + }, + "expo-status-bar": { + "version": "~1.6.0", + "alwaysAddToPackageJson": false + }, + "@expo/cli": { + "version": "~0.10.10", + "alwaysAddToPackageJson": false + }, + "eas-cli": { + "version": "~3.15.0", + "alwaysAddToPackageJson": false + }, + "babel-preset-expo": { + "version": "~9.5.0", + "alwaysAddToPackageJson": false + }, + "jest-expo": { + "version": "~49.0.0", + "alwaysAddToPackageJson": false + }, + "metro-resolver": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "metro": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "react-native": { + "version": "0.72.3", + "alwaysAddToPackageJson": false + }, + "@types/react-native": { + "version": "0.72.2", + "alwaysAddToPackageJson": false + }, + "react-native-web": { + "version": "~0.19.6", + "alwaysAddToPackageJson": false + }, + "react-native-svg": { + "version": "13.9.0", + "alwaysAddToPackageJson": false + } + } } } } diff --git a/packages/expo/package.json b/packages/expo/package.json index 50ac01e23aace7..f39394ca2ffe78 100644 --- a/packages/expo/package.json +++ b/packages/expo/package.json @@ -29,7 +29,8 @@ "chalk": "^4.1.0", "enhanced-resolve": "^5.8.3", "fs-extra": "^11.1.0", - "metro-resolver": "^0.74.1", + "metro-config": "0.76.7", + "metro-resolver": "0.76.7", "node-fetch": "^2.6.7", "tar-fs": "^2.1.1", "tsconfig-paths": "^4.1.2", @@ -43,7 +44,9 @@ "@nx/webpack": "file:../webpack" }, "peerDependencies": { - "expo": "^48.0.19" + "expo": ">= 49.0.0", + "@expo/cli": ">= 0.10.0", + "eas-cli": ">= 3.15.0" }, "builders": "./executors.json", "ng-update": { diff --git a/packages/expo/plugins/with-nx-metro.ts b/packages/expo/plugins/with-nx-metro.ts index 81ac08570064c1..943886babbb82d 100644 --- a/packages/expo/plugins/with-nx-metro.ts +++ b/packages/expo/plugins/with-nx-metro.ts @@ -1,4 +1,6 @@ import { workspaceLayout, workspaceRoot } from '@nx/devkit'; +import { mergeConfig } from 'metro-config'; +import type { MetroConfig } from 'metro-config'; import { join } from 'path'; import { existsSync } from 'fs-extra'; @@ -7,35 +9,39 @@ import { getResolveRequest } from './metro-resolver'; interface WithNxOptions { debug?: boolean; extensions?: string[]; + /** + * @deprecated in the metro.config.js, pass in to the getDefaultConfig instead: getDefaultConfig(__dirname) + */ projectRoot?: string; watchFolders?: string[]; } -export function withNxMetro(config: any, opts: WithNxOptions = {}) { +export async function withNxMetro( + userConfig: MetroConfig, + opts: WithNxOptions = {} +) { const extensions = ['', 'ts', 'tsx', 'js', 'jsx', 'json']; if (opts.debug) process.env.NX_REACT_NATIVE_DEBUG = 'true'; if (opts.extensions) extensions.push(...opts.extensions); - config.projectRoot = opts.projectRoot || workspaceRoot; - - // Add support for paths specified by tsconfig - config.resolver = { - ...config.resolver, - resolveRequest: getResolveRequest(extensions), - }; - - let watchFolders = config.watchFolders || []; - watchFolders = watchFolders.concat([ + let watchFolders = [ join(workspaceRoot, 'node_modules'), join(workspaceRoot, workspaceLayout().libsDir), join(workspaceRoot, 'packages'), - ]); + join(workspaceRoot, '.storybook'), + ]; if (opts.watchFolders?.length) { watchFolders = watchFolders.concat(opts.watchFolders); } watchFolders = watchFolders.filter((folder) => existsSync(folder)); - config.watchFolders = watchFolders; - return config; + const nxConfig: MetroConfig = { + resolver: { + resolveRequest: getResolveRequest(extensions), + }, + watchFolders, + }; + + return mergeConfig(userConfig, nxConfig); } diff --git a/packages/expo/src/executors/build-list/build-list.impl.ts b/packages/expo/src/executors/build-list/build-list.impl.ts index 65a90bffa5003a..1f2829a6f0ce78 100644 --- a/packages/expo/src/executors/build-list/build-list.impl.ts +++ b/packages/expo/src/executors/build-list/build-list.impl.ts @@ -1,5 +1,5 @@ import { ExecutorContext, logger, names } from '@nx/devkit'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; @@ -42,10 +42,10 @@ export function runCliBuildList( ): Promise { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/eas-cli/bin/run'), + require.resolve('eas-cli/bin/run'), ['build:list', ...createBuildListOptions(options)], { - cwd: join(workspaceRoot, projectRoot), + cwd: pathResolve(workspaceRoot, projectRoot), env: process.env, stdio: ['inherit', 'pipe', 'inherit', 'ipc'], // only stream stdout on child process } diff --git a/packages/expo/src/executors/build/build.impl.ts b/packages/expo/src/executors/build/build.impl.ts index fc89e7684c7424..b67fbe68b5b5e2 100644 --- a/packages/expo/src/executors/build/build.impl.ts +++ b/packages/expo/src/executors/build/build.impl.ts @@ -1,5 +1,5 @@ -import { ExecutorContext, names } from '@nx/devkit'; -import { join, normalize, sep } from 'path'; +import { ExecutorContext, names, output } from '@nx/devkit'; +import { normalize, sep, resolve as pathResolve, dirname } from 'path'; import { ChildProcess, fork } from 'child_process'; import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; @@ -20,21 +20,22 @@ export default async function* buildExecutor( ): AsyncGenerator { const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); try { // remove the output app if it already existed if (options.local && options.output) { removeSync(options.output); + if (options.output.endsWith('.tar.gz')) { + // remove unzipped app if it already existed + removeSync(options.output.replace('.tar.gz', '.app')); + } } await runCliBuild(context.root, projectRoot, options); // unzip the build if it's a tar.gz if (options.local && options.output && options.output.endsWith('.tar.gz')) { - const directoryPath = normalize(options.output).split(sep); - directoryPath.pop(); - const outputDirectory = directoryPath.join(sep); + const outputDirectory = dirname(options.output); await unzipBuild(options.output, outputDirectory); } yield { success: true }; @@ -52,10 +53,10 @@ function runCliBuild( ) { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/eas-cli/bin/run'), + require.resolve('eas-cli/bin/run'), ['build', ...createBuildOptions(options)], { - cwd: join(workspaceRoot, projectRoot), + cwd: pathResolve(workspaceRoot, projectRoot), env: process.env, } ); diff --git a/packages/expo/src/executors/build/schema.json b/packages/expo/src/executors/build/schema.json index 64c399d6ccffa8..2821cb7c2a29fb 100644 --- a/packages/expo/src/executors/build/schema.json +++ b/packages/expo/src/executors/build/schema.json @@ -55,7 +55,8 @@ }, "output": { "type": "string", - "description": "Output path for local build" + "description": "Output path for local build", + "examples": ["../../dist/MyApp.tar.gz", "../../dist"] }, "wait": { "type": "boolean", diff --git a/packages/expo/src/executors/download/download.impl.ts b/packages/expo/src/executors/download/download.impl.ts index 28dc180b427580..6d44353388e7a8 100644 --- a/packages/expo/src/executors/download/download.impl.ts +++ b/packages/expo/src/executors/download/download.impl.ts @@ -28,6 +28,7 @@ export interface ReactNativeDownloadOutput { const streamPipeline = promisify(pipeline); /** + * @deprecated this executor is to be removed in NX 17. It is no longer used. * This executor downloads the latest EAS build. * It calls the build list executor to list EAS builds with options passed in. */ diff --git a/packages/expo/src/executors/export/export.impl.ts b/packages/expo/src/executors/export/export.impl.ts index 6aecc5e28ba694..242012ce9a4673 100644 --- a/packages/expo/src/executors/export/export.impl.ts +++ b/packages/expo/src/executors/export/export.impl.ts @@ -1,8 +1,7 @@ import { ExecutorContext, names } from '@nx/devkit'; import { ChildProcess, fork } from 'child_process'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; import { ExportExecutorSchema } from './schema'; export interface ExpoExportOutput { @@ -17,7 +16,6 @@ export default async function* exportExecutor( ): AsyncGenerator { const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); try { await exportAsync(context.root, projectRoot, options); @@ -39,13 +37,13 @@ function exportAsync( ): Promise { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/@expo/cli/build/bin/cli'), + require.resolve('@expo/cli/build/bin/cli'), [ `export${options.bundler === 'webpack' ? ':web' : ''}`, '.', ...createExportOptions(options), ], - { cwd: join(workspaceRoot, projectRoot), env: process.env } + { cwd: pathResolve(workspaceRoot, projectRoot), env: process.env } ); // Ensure the child process is killed when the parent exits diff --git a/packages/expo/src/executors/install/install.impl.ts b/packages/expo/src/executors/install/install.impl.ts index 751219597718ee..ad1053ad0854b0 100644 --- a/packages/expo/src/executors/install/install.impl.ts +++ b/packages/expo/src/executors/install/install.impl.ts @@ -1,6 +1,5 @@ import { ExecutorContext, names } from '@nx/devkit'; import { ChildProcess, fork } from 'child_process'; -import { join } from 'path'; import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; import { ExpoInstallOptions } from './schema'; @@ -38,7 +37,7 @@ export function installAsync( ): Promise { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/@expo/cli/build/bin/cli'), + require.resolve('@expo/cli/build/bin/cli'), ['install', ...createInstallOptions(options)], { cwd: workspaceRoot, env: process.env } ); diff --git a/packages/expo/src/executors/prebuild/prebuild.impl.ts b/packages/expo/src/executors/prebuild/prebuild.impl.ts index 2747473cc804e5..05de40d8b7db71 100644 --- a/packages/expo/src/executors/prebuild/prebuild.impl.ts +++ b/packages/expo/src/executors/prebuild/prebuild.impl.ts @@ -27,7 +27,7 @@ export default async function* prebuildExecutor( if (options.install) { await installAsync(context.root, {}); if (options.platform === 'ios') { - await podInstall(join(context.root, projectRoot, 'ios')); + podInstall(join(context.root, projectRoot, 'ios')); } } @@ -48,7 +48,7 @@ export function prebuildAsync( ): Promise { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/@expo/cli/build/bin/cli'), + require.resolve('@expo/cli/build/bin/cli'), ['prebuild', ...createPrebuildOptions(options), '--no-install'], { cwd: join(workspaceRoot, projectRoot), env: process.env } ); diff --git a/packages/expo/src/executors/run/run.impl.ts b/packages/expo/src/executors/run/run.impl.ts index f2075f1e2c2874..902af88770a406 100644 --- a/packages/expo/src/executors/run/run.impl.ts +++ b/packages/expo/src/executors/run/run.impl.ts @@ -1,5 +1,5 @@ import { ExecutorContext, names } from '@nx/devkit'; -import { join } from 'path'; +import { join, resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; import { platform } from 'os'; import { existsSync } from 'fs-extra'; @@ -29,18 +29,6 @@ export default async function* runExecutor( } const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); - if (options.sync) { - displayNewlyAddedDepsMessage( - context.projectName, - await syncDeps( - context.projectName, - projectRoot, - context.root, - context.projectGraph - ) - ); - } if (!existsSync(join(context.root, projectRoot, options.platform))) { await prebuildAsync(context.root, projectRoot, { @@ -53,7 +41,7 @@ export default async function* runExecutor( if (options.install) { await installAsync(context.root, {}); if (options.platform === 'ios') { - await podInstall(join(context.root, projectRoot, 'ios')); + podInstall(join(context.root, projectRoot, 'ios')); } } @@ -75,10 +63,11 @@ function runCliRun( ) { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/@expo/cli/build/bin/cli'), + require.resolve('@expo/cli/build/bin/cli'), ['run:' + options.platform, ...createRunOptions(options), '--no-install'], // pass in no-install to prevent node_modules install { - cwd: projectRoot, + cwd: pathResolve(workspaceRoot, projectRoot), + env: process.env, } ); diff --git a/packages/expo/src/executors/run/schema.d.ts b/packages/expo/src/executors/run/schema.d.ts index e1e6102dd06693..db56a79286807f 100644 --- a/packages/expo/src/executors/run/schema.d.ts +++ b/packages/expo/src/executors/run/schema.d.ts @@ -6,6 +6,9 @@ export interface ExpoRunOptions { // nx options platform: 'ios' | 'android'; + /** + * @deprecated Add sync-deps to dependsOn in project.json for this target instead + */ sync: boolean; // default is true install?: boolean; // default is true clean?: boolean; // default is false diff --git a/packages/expo/src/executors/run/schema.json b/packages/expo/src/executors/run/schema.json index 3f96d584863ace..fe862b55fd9e91 100644 --- a/packages/expo/src/executors/run/schema.json +++ b/packages/expo/src/executors/run/schema.json @@ -39,6 +39,7 @@ "type": "boolean", "description": "Syncs npm dependencies to package.json (for React Native autolink).", "default": true, + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "x-priority": "internal" }, "port": { diff --git a/packages/expo/src/executors/start/schema.d.ts b/packages/expo/src/executors/start/schema.d.ts index f172b4fce1ea27..0e4d87e1eddab3 100644 --- a/packages/expo/src/executors/start/schema.d.ts +++ b/packages/expo/src/executors/start/schema.d.ts @@ -20,6 +20,8 @@ export interface ExpoStartOptions { tunnel?: boolean; offline?: boolean; - // nx options + /** + * @deprecated Add sync-deps to dependsOn in project.json for this target instead + */ sync?: boolean; // default is true } diff --git a/packages/expo/src/executors/start/schema.json b/packages/expo/src/executors/start/schema.json index 85a433da9e6634..e74466325694cb 100644 --- a/packages/expo/src/executors/start/schema.json +++ b/packages/expo/src/executors/start/schema.json @@ -91,6 +91,7 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to package.json (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "default": true } }, diff --git a/packages/expo/src/executors/start/start.impl.ts b/packages/expo/src/executors/start/start.impl.ts index 28ee17bc0628b4..46ff86162eddf4 100644 --- a/packages/expo/src/executors/start/start.impl.ts +++ b/packages/expo/src/executors/start/start.impl.ts @@ -1,14 +1,9 @@ import * as chalk from 'chalk'; import { ExecutorContext, logger, names } from '@nx/devkit'; import { ChildProcess, fork } from 'child_process'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; import { ExpoStartOptions } from './schema'; -import { - displayNewlyAddedDepsMessage, - syncDeps, -} from '../sync-deps/sync-deps.impl'; export interface ExpoStartOutput { baseUrl?: string; @@ -23,18 +18,6 @@ export default async function* startExecutor( ): AsyncGenerator { const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); - if (options.sync) { - displayNewlyAddedDepsMessage( - context.projectName, - await syncDeps( - context.projectName, - projectRoot, - context.root, - context.projectGraph - ) - ); - } try { const baseUrl = `http://localhost:${options.port}`; @@ -60,9 +43,9 @@ function startAsync( ): Promise { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/@expo/cli/build/bin/cli'), + require.resolve('@expo/cli/build/bin/cli'), ['start', ...createStartOptions(options)], - { cwd: join(workspaceRoot, projectRoot), env: process.env } + { cwd: pathResolve(workspaceRoot, projectRoot), env: process.env } ); // Ensure the child process is killed when the parent exits diff --git a/packages/expo/src/executors/submit/submit.impl.ts b/packages/expo/src/executors/submit/submit.impl.ts index d1bcbd7317ddf3..a3d6c8b3f58227 100644 --- a/packages/expo/src/executors/submit/submit.impl.ts +++ b/packages/expo/src/executors/submit/submit.impl.ts @@ -1,9 +1,7 @@ import { ExecutorContext, names } from '@nx/devkit'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; - import { SubmitExecutorSchema } from './schema'; export interface ReactNativeSubmitOutput { @@ -18,7 +16,6 @@ export default async function* submitExecutor( ): AsyncGenerator { const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); try { await runCliSubmit(context.root, projectRoot, options); @@ -38,10 +35,10 @@ function runCliSubmit( ) { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/eas-cli/bin/run'), + require.resolve('eas-cli/bin/run'), ['submit', ...createSubmitOptions(options)], { - cwd: join(workspaceRoot, projectRoot), + cwd: pathResolve(workspaceRoot, projectRoot), env: process.env, } ); diff --git a/packages/expo/src/executors/update/update.impl.ts b/packages/expo/src/executors/update/update.impl.ts index 81c04652dccd37..99e828dbfaa453 100644 --- a/packages/expo/src/executors/update/update.impl.ts +++ b/packages/expo/src/executors/update/update.impl.ts @@ -1,5 +1,5 @@ import { ExecutorContext, names } from '@nx/devkit'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; @@ -53,9 +53,9 @@ function runCliUpdate( ) { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/eas-cli/bin/run'), + require.resolve('eas-cli/bin/run'), ['update', ...createUpdateOptions(options)], - { cwd: join(workspaceRoot, projectRoot), env: process.env } + { cwd: pathResolve(workspaceRoot, projectRoot), env: process.env } ); // Ensure the child process is killed when the parent exits diff --git a/packages/expo/src/generators/application/application.spec.ts b/packages/expo/src/generators/application/application.spec.ts index 709303c2549974..2ce626375223cb 100644 --- a/packages/expo/src/generators/application/application.spec.ts +++ b/packages/expo/src/generators/application/application.spec.ts @@ -121,12 +121,6 @@ describe('app', () => { 'cd ../../../apps/my-dir/my-app/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug', type: 'android.apk', }, - 'android.eas': { - binaryPath: '../../../apps/my-dir/my-app/dist/MyApp.apk', - build: - 'npx nx run my-app:download --platform android --distribution simulator --output=../../../apps/my-dir/my-app/dist/', - type: 'android.apk', - }, 'android.local': { binaryPath: '../../../apps/my-dir/my-app/dist/MyApp.apk', build: @@ -147,12 +141,6 @@ describe('app', () => { "cd ../../../apps/my-dir/my-app/ios && xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Debug -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -derivedDataPath ./build -quiet", type: 'ios.app', }, - 'ios.eas': { - binaryPath: '../../../apps/my-dir/my-app/dist/MyApp.app', - build: - 'npx nx run my-app:download --platform ios --distribution simulator --output=../../../apps/my-dir/my-app/dist/', - type: 'ios.app', - }, 'ios.local': { binaryPath: '../../../apps/my-dir/my-app/dist/MyApp.app', build: @@ -196,12 +184,6 @@ describe('app', () => { 'cd ../../apps/my-app/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug', type: 'android.apk', }, - 'android.eas': { - binaryPath: '../../apps/my-app/dist/MyApp.apk', - build: - 'npx nx run my-app:download --platform android --distribution simulator --output=../../apps/my-app/dist/', - type: 'android.apk', - }, 'android.local': { binaryPath: '../../apps/my-app/dist/MyApp.apk', build: @@ -222,12 +204,6 @@ describe('app', () => { "cd ../../apps/my-app/ios && xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Debug -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -derivedDataPath ./build -quiet", type: 'ios.app', }, - 'ios.eas': { - binaryPath: '../../apps/my-app/dist/MyApp.app', - build: - 'npx nx run my-app:download --platform ios --distribution simulator --output=../../apps/my-app/dist/', - type: 'ios.app', - }, 'ios.local': { binaryPath: '../../apps/my-app/dist/MyApp.app', build: @@ -272,12 +248,6 @@ describe('app', () => { 'cd ../../apps/my-app/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug', type: 'android.apk', }, - 'android.eas': { - binaryPath: '../../apps/my-app/dist/myappname.apk', - build: - 'npx nx run my-app:download --platform android --distribution simulator --output=../../apps/my-app/dist/', - type: 'android.apk', - }, 'android.local': { binaryPath: '../../apps/my-app/dist/myappname.apk', build: @@ -298,12 +268,6 @@ describe('app', () => { "cd ../../apps/my-app/ios && xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Debug -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -derivedDataPath ./build -quiet", type: 'ios.app', }, - 'ios.eas': { - binaryPath: '../../apps/my-app/dist/myappname.app', - build: - 'npx nx run my-app:download --platform ios --distribution simulator --output=../../apps/my-app/dist/', - type: 'ios.app', - }, 'ios.local': { binaryPath: '../../apps/my-app/dist/myappname.app', build: diff --git a/packages/expo/src/generators/application/files/metro.config.js.template b/packages/expo/src/generators/application/files/metro.config.js.template index 792f11624b5d94..5b3d161a95497e 100644 --- a/packages/expo/src/generators/application/files/metro.config.js.template +++ b/packages/expo/src/generators/application/files/metro.config.js.template @@ -1,25 +1,37 @@ const { withNxMetro } = require('@nx/expo'); const { getDefaultConfig } = require('@expo/metro-config'); +const { mergeConfig } = require('metro-config'); +const exclusionList = require('metro-config/src/defaults/exclusionList'); const defaultConfig = getDefaultConfig(__dirname); +const { assetExts, sourceExts } = defaultConfig.resolver; -module.exports = (async () => { - defaultConfig.transformer.babelTransformerPath = require.resolve( - 'react-native-svg-transformer' - ); - defaultConfig.resolver.assetExts = defaultConfig.resolver.assetExts.filter( - (ext) => ext !== 'svg' - ); - defaultConfig.resolver.sourceExts.push('svg'); - return withNxMetro(defaultConfig, { - // Change this to true to see debugging info. - // Useful if you have issues resolving modules - debug: false, - // all the file extensions used for imports other than 'ts', 'tsx', 'js', 'jsx' - extensions: [], - // the project root to start the metro server - projectRoot: __dirname, - // Specify any additional (to projectRoot) watch folders, this is used to know which files to watch - watchFolders: [] - }); -})(); +/** + * Metro configuration + * https://facebook.github.io/metro/docs/configuration + * + * @type {import('metro-config').MetroConfig} + */ +const customConfig = { + transformer: { + babelTransformerPath: require.resolve('react-native-svg-transformer'), + }, + resolver: { + assetExts: assetExts.filter((ext) => ext !== 'svg'), + sourceExts: [...sourceExts, 'svg'], + blockList: exclusionList([/^(?!.*node_modules).*\/dist\/.*/]), + unstable_enableSymlinks: true, + unstable_enablePackageExports: true, + }, +}; + + +module.exports = withNxMetro(mergeConfig(defaultConfig, customConfig), { + // Change this to true to see debugging info. + // Useful if you have issues resolving modules + debug: false, + // all the file extensions used for imports other than 'ts', 'tsx', 'js', 'jsx', 'json' + extensions: [], + // Specify folders to watch, in addition to Nx defaults (workspace libraries and node_modules) + watchFolders: [], +}); diff --git a/packages/expo/src/generators/application/files/package.json.template b/packages/expo/src/generators/application/files/package.json.template index 95287ac2bafb08..07bb68718ee62b 100644 --- a/packages/expo/src/generators/application/files/package.json.template +++ b/packages/expo/src/generators/application/files/package.json.template @@ -5,6 +5,7 @@ "dependencies": { "@testing-library/jest-native": "*", "@testing-library/react-native": "*", + "metro-config": "*", "react-native": "*", "expo": "*", "react-native-svg": "*", diff --git a/packages/expo/src/generators/application/lib/add-project.ts b/packages/expo/src/generators/application/lib/add-project.ts index f158ab67992ee1..d0484277800b06 100644 --- a/packages/expo/src/generators/application/lib/add-project.ts +++ b/packages/expo/src/generators/application/lib/add-project.ts @@ -29,6 +29,7 @@ function getTargets(options: NormalizedSchema) { architect.start = { executor: '@nx/expo:start', + dependsOn: ['ensure-symlink', 'sync-deps'], options: { port: 8081, }, @@ -43,6 +44,7 @@ function getTargets(options: NormalizedSchema) { architect['run-ios'] = { executor: '@nx/expo:run', + dependsOn: ['ensure-symlink', 'sync-deps'], options: { platform: 'ios', }, @@ -50,6 +52,7 @@ function getTargets(options: NormalizedSchema) { architect['run-android'] = { executor: '@nx/expo:run', + dependsOn: ['ensure-symlink', 'sync-deps'], options: { platform: 'android', }, @@ -70,6 +73,9 @@ function getTargets(options: NormalizedSchema) { options: {}, }; + /** + * @deprecated To be removed in NX 17 + */ architect['download'] = { executor: '@nx/expo:download', options: { @@ -89,6 +95,7 @@ function getTargets(options: NormalizedSchema) { architect['prebuild'] = { executor: '@nx/expo:prebuild', + dependsOn: ['ensure-symlink', 'sync-deps'], options: {}, }; @@ -104,6 +111,7 @@ function getTargets(options: NormalizedSchema) { architect['export'] = { executor: '@nx/expo:export', + dependsOn: ['ensure-symlink', 'sync-deps'], options: { platform: 'all', outputDir: `${offsetFromRoot(options.appProjectRoot)}dist/${ diff --git a/packages/expo/src/migrations/update-16-6-0/add-depends-on.ts b/packages/expo/src/migrations/update-16-6-0/add-depends-on.ts new file mode 100644 index 00000000000000..3b826e59130817 --- /dev/null +++ b/packages/expo/src/migrations/update-16-6-0/add-depends-on.ts @@ -0,0 +1,21 @@ +import { Tree, getProjects, updateProjectConfiguration } from '@nx/devkit'; + +/** + * This migration adds dependsOn to project.json. + * + */ +export default async function update(tree: Tree) { + const projects = getProjects(tree); + + for (const [name, config] of projects.entries()) { + if (config.targets?.['start']?.executor === '@nx/expo:start') { + config.targets['start'].dependsOn = ['ensure-symlink', 'sync-deps']; + config.targets['run-ios'].dependsOn = ['ensure-symlink', 'sync-deps']; + config.targets['run-android'].dependsOn = ['ensure-symlink', 'sync-deps']; + config.targets['prebuild'].dependsOn = ['ensure-symlink', 'sync-deps']; + config.targets['export'].dependsOn = ['ensure-symlink', 'sync-deps']; + + updateProjectConfiguration(tree, name, config); + } + } +} diff --git a/packages/expo/src/migrations/update-16-6-0/update-metro-config.ts b/packages/expo/src/migrations/update-16-6-0/update-metro-config.ts new file mode 100644 index 00000000000000..7a33017c93cab9 --- /dev/null +++ b/packages/expo/src/migrations/update-16-6-0/update-metro-config.ts @@ -0,0 +1,58 @@ +import { Tree, getProjects } from '@nx/devkit'; +import { join } from 'path'; + +/** + * This migration updates metro.config.js to export config as a default. + * + */ +export default async function update(tree: Tree) { + const projects = getProjects(tree); + + for (const [_, config] of projects.entries()) { + if (config.targets?.['start']?.executor === '@nx/expo:start') { + if (tree.exists(join(config.root, 'metro.config.js'))) { + tree.write(join(config.root, 'metro.config.js'), content); + } + } + } +} + +const content = ` +const { withNxMetro } = require('@nx/expo'); +const { getDefaultConfig } = require('@expo/metro-config'); +const { mergeConfig } = require('metro-config'); +const exclusionList = require('metro-config/src/defaults/exclusionList'); + +const defaultConfig = getDefaultConfig(__dirname); +const { assetExts, sourceExts } = defaultConfig.resolver; + +/** + * Metro configuration + * https://facebook.github.io/metro/docs/configuration + * + * @type {import('metro-config').MetroConfig} + */ +const customConfig = { + transformer: { + babelTransformerPath: require.resolve('react-native-svg-transformer'), + }, + resolver: { + assetExts: assetExts.filter((ext) => ext !== 'svg'), + sourceExts: [...sourceExts, 'svg'], + blockList: exclusionList([/^(?!.*node_modules).*\/dist\/.*/]), + unstable_enableSymlinks: true, + unstable_enablePackageExports: true, + }, +}; + + +module.exports = withNxMetro(mergeConfig(defaultConfig, customConfig), { + // Change this to true to see debugging info. + // Useful if you have issues resolving modules + debug: false, + // all the file extensions used for imports other than 'ts', 'tsx', 'js', 'jsx', 'json' + extensions: [], + // Specify folders to watch, in addition to Nx defaults (workspace libraries and node_modules) + watchFolders: [], +}); +`; diff --git a/packages/expo/src/utils/versions.ts b/packages/expo/src/utils/versions.ts index a494bd29a0ac28..0dcbd8136fc9c8 100644 --- a/packages/expo/src/utils/versions.ts +++ b/packages/expo/src/utils/versions.ts @@ -1,28 +1,27 @@ export const nxVersion = require('../../package.json').version; -export const expoVersion = '48.0.19'; -export const expoMetroConfigVersion = '0.7.1'; -export const expoSplashScreenVersion = '~0.18.2'; -export const expoStatusBarVersion = '~1.4.4'; -export const expoUpdatesVersion = '~0.16.4'; -export const expoCliVersion = '~0.7.3'; // @expo/cli -export const easCliVersion = '~3.13.3'; -export const babelPresetExpoVersion = '~9.3.2'; +export const expoVersion = '49.0.3'; +export const expoMetroConfigVersion = '~0.10.6'; +export const expoSplashScreenVersion = '~0.20.4'; +export const expoStatusBarVersion = '~1.6.0'; +export const expoCliVersion = '~0.10.10'; // @expo/cli +export const easCliVersion = '~3.15.1'; +export const babelPresetExpoVersion = '~9.5.0'; export const reactVersion = '18.2.0'; export const reactDomVersion = '18.2.0'; export const reactTestRendererVersion = '18.2.0'; export const typesReactVersion = '18.0.28'; -export const reactNativeVersion = '0.71.8'; -export const typesReactNativeVersion = '0.71.7'; -export const reactNativeWebVersion = '~0.18.12'; +export const reactNativeVersion = '0.72.3'; +export const typesReactNativeVersion = '0.72.2'; +export const reactNativeWebVersion = '~0.19.6'; export const reactNativeSvgTransformerVersion = '1.0.0'; -export const reactNativeSvgVersion = '13.4.0'; +export const reactNativeSvgVersion = '13.9.0'; -export const metroVersion = '0.74.1'; +export const metroVersion = '0.76.7'; export const testingLibraryReactNativeVersion = '12.1.2'; export const testingLibraryJestNativeVersion = '5.4.2'; -export const jestExpoVersion = '~48.0.2'; +export const jestExpoVersion = '~49.0.0'; diff --git a/packages/react-native/migrations.json b/packages/react-native/migrations.json index 2615b50013cf0e..d11fb1032df341 100644 --- a/packages/react-native/migrations.json +++ b/packages/react-native/migrations.json @@ -89,6 +89,18 @@ "version": "16.1.0-beta.0", "description": "Upgrade @storybook/react-native to 6.5", "implementation": "./src/migrations/update-16-1-0/upgrade-storybook-6-5" + }, + "update-16-6-0-add-dependsOn": { + "cli": "nx", + "version": "16.6.0-beta.0", + "description": "Add dependsOn like ensure-symlink or sync-deps to targets", + "implementation": "./src/migrations/update-16-6-0/add-depends-on" + }, + "update-16-6-0-update-metro-config": { + "cli": "nx", + "version": "16.6.0-beta.0", + "description": "Update metro.config.js to use the new metro config format", + "implementation": "./src/migrations/update-16-6-0/update-metro-config" } }, "packageJsonUpdates": { @@ -1348,6 +1360,72 @@ "alwaysAddToPackageJson": false } } + }, + "16.6.0": { + "version": "16.6.0-beta.0", + "packages": { + "react-native": { + "version": "0.72.3", + "alwaysAddToPackageJson": false + }, + "@types/react-native": { + "version": "0.72.2", + "alwaysAddToPackageJson": false + }, + "metro": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "metro-resolver": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "metro-config": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "metro-react-native-babel-preset": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "metro-babel-register": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "metro-react-native-babel-transformer": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "@react-native/metro-config": { + "version": "^0.72.9", + "alwaysAddToPackageJson": false, + "addToPackageJson": "devDependencies" + }, + "@react-native-community/cli": { + "version": "11.3.5", + "alwaysAddToPackageJson": false + }, + "@react-native-community/cli-platform-android": { + "version": "11.3.5", + "alwaysAddToPackageJson": false + }, + "@react-native-community/cli-platform-ios": { + "version": "11.3.5", + "alwaysAddToPackageJson": false + }, + "@babel/runtime": { + "version": "7.22.6", + "alwaysAddToPackageJson": false + }, + "@react-native-async-storage/async-storage": { + "version": "1.19.0", + "alwaysAddToPackageJson": false + }, + "react-native-safe-area-context": { + "version": "4.7.1", + "alwaysAddToPackageJson": false + } + } } } } diff --git a/packages/react-native/package.json b/packages/react-native/package.json index 0231e5e88d8ef3..7aa7ef0cd198d1 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -30,7 +30,8 @@ "fs-extra": "^11.1.0", "glob": "7.1.4", "ignore": "^5.0.4", - "metro-resolver": "^0.74.1", + "metro-config": "0.76.7", + "metro-resolver": "0.76.7", "minimatch": "3.0.5", "node-fetch": "^2.6.7", "tsconfig-paths": "^4.1.2", @@ -43,7 +44,7 @@ "@nx/workspace": "file:../workspace" }, "peerDependencies": { - "react-native": ">= 0.71.0" + "react-native": ">= 0.72.0 < 0.73.0" }, "builders": "./executors.json", "ng-update": { diff --git a/packages/react-native/plugins/with-nx-metro.ts b/packages/react-native/plugins/with-nx-metro.ts index 6bf66f767af324..943886babbb82d 100644 --- a/packages/react-native/plugins/with-nx-metro.ts +++ b/packages/react-native/plugins/with-nx-metro.ts @@ -1,4 +1,6 @@ import { workspaceLayout, workspaceRoot } from '@nx/devkit'; +import { mergeConfig } from 'metro-config'; +import type { MetroConfig } from 'metro-config'; import { join } from 'path'; import { existsSync } from 'fs-extra'; @@ -7,36 +9,39 @@ import { getResolveRequest } from './metro-resolver'; interface WithNxOptions { debug?: boolean; extensions?: string[]; + /** + * @deprecated in the metro.config.js, pass in to the getDefaultConfig instead: getDefaultConfig(__dirname) + */ projectRoot?: string; watchFolders?: string[]; } -export function withNxMetro(config: any, opts: WithNxOptions = {}) { +export async function withNxMetro( + userConfig: MetroConfig, + opts: WithNxOptions = {} +) { const extensions = ['', 'ts', 'tsx', 'js', 'jsx', 'json']; if (opts.debug) process.env.NX_REACT_NATIVE_DEBUG = 'true'; if (opts.extensions) extensions.push(...opts.extensions); - config.projectRoot = opts.projectRoot || workspaceRoot; - - // Add support for paths specified by tsconfig - config.resolver = { - ...config.resolver, - resolveRequest: getResolveRequest(extensions), - }; - - let watchFolders = config.watchFolders || []; - watchFolders = watchFolders.concat([ + let watchFolders = [ join(workspaceRoot, 'node_modules'), join(workspaceRoot, workspaceLayout().libsDir), join(workspaceRoot, 'packages'), join(workspaceRoot, '.storybook'), - ]); + ]; if (opts.watchFolders?.length) { watchFolders = watchFolders.concat(opts.watchFolders); } watchFolders = watchFolders.filter((folder) => existsSync(folder)); - config.watchFolders = watchFolders; - return config; + const nxConfig: MetroConfig = { + resolver: { + resolveRequest: getResolveRequest(extensions), + }, + watchFolders, + }; + + return mergeConfig(userConfig, nxConfig); } diff --git a/packages/react-native/src/executors/build-android/build-android.impl.ts b/packages/react-native/src/executors/build-android/build-android.impl.ts index e6082d2d64f537..82f77380bd181b 100644 --- a/packages/react-native/src/executors/build-android/build-android.impl.ts +++ b/packages/react-native/src/executors/build-android/build-android.impl.ts @@ -1,62 +1,24 @@ -import { ExecutorContext, names } from '@nx/devkit'; -import { join } from 'path'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; +import { ExecutorContext } from '@nx/devkit'; +import { join, resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; import { ReactNativeBuildAndroidOptions } from './schema'; import { chmodAndroidGradlewFiles } from '../../utils/chmod-android-gradle-files'; -import { runCliStart } from '../start/start.impl'; -import { - displayNewlyAddedDepsMessage, - syncDeps, -} from '../sync-deps/sync-deps.impl'; import { getCliOptions } from '../../utils/get-cli-options'; export interface ReactNativeBuildOutput { success: boolean; } -let childProcess: ChildProcess; - export default async function* buildAndroidExecutor( options: ReactNativeBuildAndroidOptions, context: ExecutorContext ): AsyncGenerator { const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); - if (options.sync) { - displayNewlyAddedDepsMessage( - context.projectName, - await syncDeps( - context.projectName, - projectRoot, - context.root, - context.projectGraph - ) - ); - } - chmodAndroidGradlewFiles(join(projectRoot, 'android')); - try { - const tasks = [runCliBuild(context.root, projectRoot, options)]; - if (options.packager && options.mode !== 'release') { - tasks.push( - runCliStart(context.root, projectRoot, { - port: options.port, - resetCache: options.resetCache, - interactive: options.interactive, - }) - ); - } - - await Promise.all(tasks); - yield { success: true }; - } finally { - if (childProcess) { - childProcess.kill(); - } - } + await runCliBuild(context.root, projectRoot, options); + yield { success: true }; } function runCliBuild( @@ -64,30 +26,37 @@ function runCliBuild( projectRoot: string, options: ReactNativeBuildAndroidOptions ) { - return new Promise((resolve, reject) => { + return new Promise((res, reject) => { /** * Call the react native cli with option `--no-packager` * Not passing '--packager' due to cli will launch start command from the project root */ - childProcess = fork( - join(workspaceRoot, './node_modules/react-native/cli.js'), + const childProcess = fork( + require.resolve('react-native/cli.js'), ['build-android', ...createBuildAndroidOptions(options), '--no-packager'], { - cwd: join(workspaceRoot, projectRoot), + stdio: 'inherit', + cwd: pathResolve(workspaceRoot, projectRoot), env: { ...process.env, RCT_METRO_PORT: options.port.toString() }, } ); - // Ensure the child process is killed when the parent exits - process.on('exit', () => childProcess.kill()); - process.on('SIGTERM', () => childProcess.kill()); + /** + * Ensure the child process is killed when the parent exits + */ + const processExitListener = (signal?: number | NodeJS.Signals) => () => + childProcess.kill(signal); + process.on('exit', processExitListener); + process.on('SIGTERM', processExitListener); + process.on('SIGINT', processExitListener); + process.on('SIGQUIT', processExitListener); childProcess.on('error', (err) => { reject(err); }); childProcess.on('exit', (code) => { if (code === 0) { - resolve(code); + res(childProcess); } else { reject(code); } diff --git a/packages/react-native/src/executors/build-android/schema.d.ts b/packages/react-native/src/executors/build-android/schema.d.ts index 24c8d29ce7401f..712fe677901396 100644 --- a/packages/react-native/src/executors/build-android/schema.d.ts +++ b/packages/react-native/src/executors/build-android/schema.d.ts @@ -1,4 +1,5 @@ // options taken from https://github.com/react-native-community/cli/blob/main/packages/cli-platform-android/src/commands/buildAndroid/index.ts +// https://github.com/react-native-community/cli/blob/main/packages/cli-platform-android/README.md#build-android import { ReactNativeStartOptions } from '../start/schema'; @@ -20,12 +21,13 @@ export interface ReactNativeBuildAndroidOptions // react native options mode: string; // default is debug activeArchOnly: boolean; // default is false - port: number; // default is 8081 - tasks?: Array; + tasks?: string | Array; extraParams?: Array; - interactive?: boolean; + interactive: boolean; // nx options + // @deprecated, no longer used packager: boolean; // default is true + // @deprecated, add to sync-deps to dependsOn sync: boolean; } diff --git a/packages/react-native/src/executors/build-android/schema.json b/packages/react-native/src/executors/build-android/schema.json index 16284032ae8cbd..d2d5426aa26912 100644 --- a/packages/react-native/src/executors/build-android/schema.json +++ b/packages/react-native/src/executors/build-android/schema.json @@ -51,7 +51,8 @@ "packager": { "type": "boolean", "description": "Launch packager while building", - "default": true + "default": true, + "x-deprecated": "Run `nx run :start` instead. Will be removed in Nx 17." }, "port": { "type": "number", @@ -59,10 +60,10 @@ "default": 8081 }, "tasks": { - "type": "array", - "items": { - "type": "string" - }, + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Run custom Gradle tasks. By default it's \"assembleDebug\". Will override passed mode and variant arguments.", "examples": [ "assembleDebug", @@ -79,8 +80,12 @@ "default": false }, "extraParams": { - "type": "string", - "description": "Custom params passed to gradle build command" + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], + "description": "Custom params passed to gradle build command", + "examples": ["-x lint -x test"] }, "interactive": { "type": "boolean", @@ -89,7 +94,8 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", - "default": true + "default": true, + "x-deprecated": "Add sync-deps to dependsOn instead" }, "resetCache": { "type": "boolean", diff --git a/packages/react-native/src/executors/build-ios/build-ios.impl.ts b/packages/react-native/src/executors/build-ios/build-ios.impl.ts index 7b58775717f8b9..9c4fb7007df84d 100644 --- a/packages/react-native/src/executors/build-ios/build-ios.impl.ts +++ b/packages/react-native/src/executors/build-ios/build-ios.impl.ts @@ -1,25 +1,16 @@ import { ExecutorContext } from '@nx/devkit'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; import { platform } from 'os'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; -import { - displayNewlyAddedDepsMessage, - syncDeps, -} from '../sync-deps/sync-deps.impl'; -import { podInstall } from '../../utils/pod-install-task'; import { ReactNativeBuildIosOptions } from './schema'; -import { runCliStart } from '../start/start.impl'; import { getCliOptions } from '../../utils/get-cli-options'; export interface ReactNativeBuildIosOutput { success: boolean; } -let childProcess: ChildProcess; - -export default async function* runIosExecutor( +export default async function* buildIosExecutor( options: ReactNativeBuildIosOptions, context: ExecutorContext ): AsyncGenerator { @@ -28,77 +19,46 @@ export default async function* runIosExecutor( } const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); - if (options.sync) { - displayNewlyAddedDepsMessage( - context.projectName, - await syncDeps( - context.projectName, - projectRoot, - context.root, - context.projectGraph - ) - ); - } - - if (options.install) { - await podInstall( - join(context.root, projectRoot, 'ios'), - options.buildFolder - ); - } - - try { - const tasks = [runCliBuildIOS(context.root, projectRoot, options)]; - if (options.packager && options.mode !== 'Release') { - tasks.push( - runCliStart(context.root, projectRoot, { - port: options.port, - resetCache: options.resetCache, - interactive: options.interactive, - }) - ); - } - await Promise.all(tasks); - - yield { success: true }; - } finally { - if (childProcess) { - childProcess.kill(); - } - } + await runCliBuildIOS(context.root, projectRoot, options); + return { success: true }; } function runCliBuildIOS( workspaceRoot: string, projectRoot: string, options: ReactNativeBuildIosOptions -) { - return new Promise((resolve, reject) => { - /** - * Call the react native cli with option `--no-packager` - * Not passing '--packager' due to cli will launch start command from the project root - */ - childProcess = fork( - join(workspaceRoot, './node_modules/react-native/cli.js'), - ['build-ios', ...createBuildIOSOptions(options)], +): Promise { + return new Promise((resolve, reject) => { + const childProcess = fork( + require.resolve('react-native/cli.js'), + [ + 'build-ios', + ...createBuildIOSOptions(options), + ...(process.env.NX_VERBOSE_LOGGING === 'true' ? ['--verbose'] : []), + ], { - cwd: join(workspaceRoot, projectRoot), + cwd: pathResolve(workspaceRoot, projectRoot), env: { ...process.env, RCT_METRO_PORT: options.port.toString() }, } ); - // Ensure the child process is killed when the parent exits - process.on('exit', () => childProcess.kill()); - process.on('SIGTERM', () => childProcess.kill()); + /** + * Ensure the child process is killed when the parent exits + */ + const processExitListener = (signal?: number | NodeJS.Signals) => () => + childProcess.kill(signal); + process.on('exit', processExitListener); + process.on('SIGTERM', processExitListener); + process.on('SIGINT', processExitListener); + process.on('SIGQUIT', processExitListener); childProcess.on('error', (err) => { reject(err); }); childProcess.on('exit', (code) => { if (code === 0) { - resolve(code); + resolve(childProcess); } else { reject(code); } diff --git a/packages/react-native/src/executors/build-ios/schema.d.ts b/packages/react-native/src/executors/build-ios/schema.d.ts index df4fac0ecc331a..974d3271bf9d48 100644 --- a/packages/react-native/src/executors/build-ios/schema.d.ts +++ b/packages/react-native/src/executors/build-ios/schema.d.ts @@ -16,7 +16,10 @@ export interface ReactNativeBuildIosOptions extends ReactNativeStartOptions { extraParams?: string; // nx options + // @deprecated, no longer used packager: boolean; // default is true + // @deprecated, add to pod-install to dependsOn install: boolean; // default is true + // @deprecated, add to sync-deps to dependsOn sync: boolean; // default is true } diff --git a/packages/react-native/src/executors/build-ios/schema.json b/packages/react-native/src/executors/build-ios/schema.json index a23017767b4113..1036e8f4c5eaa0 100644 --- a/packages/react-native/src/executors/build-ios/schema.json +++ b/packages/react-native/src/executors/build-ios/schema.json @@ -17,10 +17,6 @@ { "name": "Build iOS for a device with udid", "keys": ["udid"] - }, - { - "name": "Run `pod install` before building iOS app", - "keys": ["install"] } ], "properties": { @@ -78,17 +74,22 @@ "description": "Explicitly select which scheme and configuration to use before running a build" }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params that will be passed to xcodebuild command." }, "install": { "type": "boolean", "description": "Runs `pod install` for native modules before building iOS app.", + "x-deprecated": "Add pod-install to dependsOn in project.json for this target instead", "default": true }, "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "default": true }, "resetCache": { @@ -99,7 +100,8 @@ "packager": { "type": "boolean", "description": "Launch packager while building", - "default": true + "default": true, + "x-deprecated": "Run `nx run :start` instead. Will be removed in Nx 17." } }, "required": [], diff --git a/packages/react-native/src/executors/bundle/bundle.impl.ts b/packages/react-native/src/executors/bundle/bundle.impl.ts index 42f4a9004465f3..64df66ead0b75f 100644 --- a/packages/react-native/src/executors/bundle/bundle.impl.ts +++ b/packages/react-native/src/executors/bundle/bundle.impl.ts @@ -1,18 +1,14 @@ import { createDirectory } from '@nx/workspace/src/utilities/fileutils'; import { names, ExecutorContext } from '@nx/devkit'; -import { dirname, join } from 'path'; +import { dirname, join, resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; - import { ReactNativeBundleOptions } from './schema'; export interface ReactNativeBundleOutput { success: boolean; } -let childProcess: ChildProcess; - export default async function* bundleExecutor( options: ReactNativeBundleOptions, context: ExecutorContext @@ -23,41 +19,44 @@ export default async function* bundleExecutor( options.bundleOutput = join(context.root, options.bundleOutput); createDirectory(dirname(options.bundleOutput)); - ensureNodeModulesSymlink(context.root, projectRoot); - try { - await runCliBuild(context.root, projectRoot, options); - yield { success: true }; - } finally { - if (childProcess) { - childProcess.kill(); - } - } + await runCliBuild(context.root, projectRoot, options); + yield { success: true }; } function runCliBuild( workspaceRoot: string, projectRoot: string, options: ReactNativeBundleOptions -) { - return new Promise((resolve, reject) => { +): Promise { + return new Promise((resolve, reject) => { const cliOptions = createBundleOptions(options); - childProcess = fork( - join(workspaceRoot, './node_modules/react-native/cli.js'), + const childProcess = fork( + require.resolve('react-native/cli.js'), ['bundle', ...cliOptions], - { cwd: join(workspaceRoot, projectRoot), env: process.env } + { + stdio: 'inherit', + cwd: pathResolve(workspaceRoot, projectRoot), + env: process.env, + } ); - // Ensure the child process is killed when the parent exits - process.on('exit', () => childProcess.kill()); - process.on('SIGTERM', () => childProcess.kill()); + /** + * Ensure the child process is killed when the parent exits + */ + const processExitListener = (signal?: number | NodeJS.Signals) => () => + childProcess.kill(signal); + process.on('exit', processExitListener); + process.on('SIGTERM', processExitListener); + process.on('SIGINT', processExitListener); + process.on('SIGQUIT', processExitListener); childProcess.on('error', (err) => { reject(err); }); childProcess.on('exit', (code) => { if (code === 0) { - resolve(code); + resolve(childProcess); } else { reject(code); } diff --git a/packages/react-native/src/executors/pod-install/pod-install.impl.ts b/packages/react-native/src/executors/pod-install/pod-install.impl.ts index c4a283fca05d4e..8ec0f80cffdb87 100644 --- a/packages/react-native/src/executors/pod-install/pod-install.impl.ts +++ b/packages/react-native/src/executors/pod-install/pod-install.impl.ts @@ -15,7 +15,7 @@ export default async function* podInstall( const projectRoot = context.projectsConfigurations.projects[context.projectName].root; const iosDirectory = join(context.root, projectRoot, 'ios'); - await runPodInstall(iosDirectory, true, options.buildFolder)(); + await runPodInstall(iosDirectory, true, options)(); yield { success: true }; } diff --git a/packages/react-native/src/executors/pod-install/schema.d.ts b/packages/react-native/src/executors/pod-install/schema.d.ts index 11f7664df8e041..41f36baf08d81f 100644 --- a/packages/react-native/src/executors/pod-install/schema.d.ts +++ b/packages/react-native/src/executors/pod-install/schema.d.ts @@ -1,3 +1,5 @@ export interface ReactNativePodInstallOptions { - buildFolder: string; + buildFolder: string; // default is './build' + repoUpdate: boolean; // default is false + deployment: boolean; // default is false } diff --git a/packages/react-native/src/executors/pod-install/schema.json b/packages/react-native/src/executors/pod-install/schema.json index 0cc954d982e9e8..e6e373c4c756fd 100644 --- a/packages/react-native/src/executors/pod-install/schema.json +++ b/packages/react-native/src/executors/pod-install/schema.json @@ -9,9 +9,19 @@ "type": "object", "properties": { "buildFolder": { - "description": "Location for iOS build artifacts. Corresponds to Xcode's \"-derivedDataPath\". Relative to ios directory", + "description": "Location for iOS build artifacts. Corresponds to Xcode's \"-derivedDataPath\". Relative to ios directory.", "type": "string", "default": "./build" + }, + "repoUpdate": { + "description": "Force running `pod repo update` before install.", + "type": "boolean", + "default": false + }, + "deployment": { + "description": "Disallow any changes to the Podfile or the Podfile.lock during installation.", + "type": "boolean", + "default": false } }, "required": ["buildFolder"] diff --git a/packages/react-native/src/executors/run-android/run-android.impl.ts b/packages/react-native/src/executors/run-android/run-android.impl.ts index a73b3c197bbb95..c63a1da59ed640 100644 --- a/packages/react-native/src/executors/run-android/run-android.impl.ts +++ b/packages/react-native/src/executors/run-android/run-android.impl.ts @@ -1,14 +1,9 @@ import { ExecutorContext } from '@nx/devkit'; -import { join } from 'path'; +import { join, resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; -import { - displayNewlyAddedDepsMessage, - syncDeps, -} from '../sync-deps/sync-deps.impl'; import { ReactNativeRunAndroidOptions } from './schema'; -import { runCliStart } from '../start/start.impl'; +import startExecutor from '../start/start.impl'; import { chmodAndroidGradlewFiles } from '../../utils/chmod-android-gradle-files'; import { getCliOptions } from '../../utils/get-cli-options'; @@ -24,72 +19,71 @@ export default async function* runAndroidExecutor( ): AsyncGenerator { const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); chmodAndroidGradlewFiles(join(projectRoot, 'android')); - if (options.sync) { - displayNewlyAddedDepsMessage( - context.projectName, - await syncDeps( - context.projectName, - projectRoot, - context.root, - context.projectGraph - ) + await runCliRunAndroid(context.root, projectRoot, options); + if (options.packager && options.mode !== 'Release') { + const startResults = startExecutor( + { + port: options.port, + resetCache: options.resetCache, + interactive: true, + }, + context ); - } - - try { - const tasks = [runCliRunAndroid(context.root, projectRoot, options)]; - if (options.packager) { - tasks.push( - runCliStart(context.root, projectRoot, { - port: options.port, - resetCache: options.resetCache, - interactive: options.interactive, - }) - ); - } - - await Promise.all(tasks); - - yield { success: true }; - } finally { - if (childProcess) { - childProcess.kill(); + for await (const result of startResults) { + if (result.success) { + await runCliRunAndroid(context.root, projectRoot, options); + yield { + success: true, + }; + } else { + return result; + } } + } else { + await runCliRunAndroid(context.root, projectRoot, options); } + + yield { success: true }; } function runCliRunAndroid( workspaceRoot: string, projectRoot: string, options: ReactNativeRunAndroidOptions -) { - return new Promise((resolve, reject) => { +): Promise { + return new Promise((resolve, reject) => { /** * Call the react native cli with option `--no-packager` * Not passing '--packager' due to cli will launch start command from the project root */ childProcess = fork( - join(workspaceRoot, './node_modules/react-native/cli.js'), + require.resolve('react-native/cli.js'), ['run-android', ...createRunAndroidOptions(options), '--no-packager'], { - cwd: join(workspaceRoot, projectRoot), + stdio: 'inherit', + cwd: pathResolve(workspaceRoot, projectRoot), env: { ...process.env, RCT_METRO_PORT: options.port.toString() }, } ); - // Ensure the child process is killed when the parent exits - process.on('exit', () => childProcess.kill()); - process.on('SIGTERM', () => childProcess.kill()); + /** + * Ensure the child process is killed when the parent exits + */ + const processExitListener = (signal?: number | NodeJS.Signals) => () => + childProcess.kill(signal); + process.on('exit', processExitListener); + process.on('SIGTERM', processExitListener); + process.on('SIGINT', processExitListener); + process.on('SIGQUIT', processExitListener); childProcess.on('error', (err) => { reject(err); }); childProcess.on('exit', (code) => { if (code === 0) { - resolve(code); + resolve(childProcess); } else { reject(code); } diff --git a/packages/react-native/src/executors/run-android/schema.json b/packages/react-native/src/executors/run-android/schema.json index 41614a3ea66158..1854d664cd999a 100644 --- a/packages/react-native/src/executors/run-android/schema.json +++ b/packages/react-native/src/executors/run-android/schema.json @@ -77,10 +77,10 @@ "default": 8081 }, "tasks": { - "type": "array", - "items": { - "type": "string" - }, + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Run custom Gradle tasks. By default it's \"assembleDebug\". Will override passed mode and variant arguments.", "examples": [ "assembleDebug", @@ -97,7 +97,10 @@ "default": false }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params passed to gradle build command" }, "interactive": { @@ -107,6 +110,7 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn for this target in project.json instead", "default": true }, "resetCache": { diff --git a/packages/react-native/src/executors/run-ios/run-ios.impl.ts b/packages/react-native/src/executors/run-ios/run-ios.impl.ts index 62b4581e7ef755..8709509d78c46e 100644 --- a/packages/react-native/src/executors/run-ios/run-ios.impl.ts +++ b/packages/react-native/src/executors/run-ios/run-ios.impl.ts @@ -1,24 +1,16 @@ import { ExecutorContext } from '@nx/devkit'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; import { platform } from 'os'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; -import { - displayNewlyAddedDepsMessage, - syncDeps, -} from '../sync-deps/sync-deps.impl'; -import { podInstall } from '../../utils/pod-install-task'; -import { ReactNativeRunIosOptions } from './schema'; -import { runCliStart } from '../start/start.impl'; +import startExecutor from '../start/start.impl'; import { getCliOptions } from '../../utils/get-cli-options'; +import { ReactNativeRunIosOptions } from './schema'; export interface ReactNativeRunIosOutput { success: boolean; } -let childProcess: ChildProcess; - export default async function* runIosExecutor( options: ReactNativeRunIosOptions, context: ExecutorContext @@ -28,77 +20,69 @@ export default async function* runIosExecutor( } const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); - if (options.sync) { - displayNewlyAddedDepsMessage( - context.projectName, - await syncDeps( - context.projectName, - projectRoot, - context.root, - context.projectGraph - ) - ); - } - if (options.install) { - await podInstall( - join(context.root, projectRoot, 'ios'), - options.buildFolder + if (options.packager && options.mode !== 'Release') { + const startResults = startExecutor( + { + port: options.port, + resetCache: options.resetCache, + interactive: true, + }, + context ); - } - - try { - const tasks = [runCliRunIOS(context.root, projectRoot, options)]; - if (options.packager && options.mode !== 'Release') { - tasks.push( - runCliStart(context.root, projectRoot, { - port: options.port, - resetCache: options.resetCache, - interactive: options.interactive, - }) - ); - } - - await Promise.all(tasks); - - yield { success: true }; - } finally { - if (childProcess) { - childProcess.kill(); + for await (const result of startResults) { + if (result.success) { + await runCliRunIOS(context.root, projectRoot, options); + yield { + success: true, + }; + } else { + return result; + } } + } else { + await runCliRunIOS(context.root, projectRoot, options); } + + yield { success: true }; } function runCliRunIOS( workspaceRoot: string, projectRoot: string, options: ReactNativeRunIosOptions -) { - return new Promise((resolve, reject) => { +): Promise { + return new Promise((resolve, reject) => { /** * Call the react native cli with option `--no-packager` * Not passing '--packager' due to cli will launch start command from the project root */ - childProcess = fork( - join(workspaceRoot, './node_modules/react-native/cli.js'), + const childProcess = fork( + require.resolve('react-native/cli.js'), ['run-ios', ...createRunIOSOptions(options), '--no-packager'], { - cwd: join(workspaceRoot, projectRoot), + stdio: 'inherit', + cwd: pathResolve(workspaceRoot, projectRoot), env: { ...process.env, RCT_METRO_PORT: options.port.toString() }, } ); - // Ensure the child process is killed when the parent exits - process.on('exit', () => childProcess.kill()); - process.on('SIGTERM', () => childProcess.kill()); + /** + * Ensure the child process is killed when the parent exits + */ + const processExitListener = (signal?: number | NodeJS.Signals) => () => + childProcess.kill(signal); + process.on('exit', processExitListener); + process.on('SIGTERM', processExitListener); + process.on('SIGINT', processExitListener); + process.on('SIGQUIT', processExitListener); childProcess.on('error', (err) => { reject(err); }); childProcess.on('exit', (code) => { if (code === 0) { - resolve(code); + resolve(childProcess); } else { reject(code); } diff --git a/packages/react-native/src/executors/run-ios/schema.json b/packages/react-native/src/executors/run-ios/schema.json index ca1182d5b473af..e23f006c61035a 100644 --- a/packages/react-native/src/executors/run-ios/schema.json +++ b/packages/react-native/src/executors/run-ios/schema.json @@ -19,10 +19,6 @@ { "name": "Run iOS on a device with udid", "keys": ["udid"] - }, - { - "name": "Run `pod install` before building iOS app", - "keys": ["install"] } ], "properties": { @@ -87,17 +83,22 @@ "description": "Explicitly select which scheme and configuration to use before running a build" }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params that will be passed to xcodebuild command." }, "install": { "type": "boolean", "description": "Runs `pod install` for native modules before building iOS app.", - "default": true + "default": true, + "x-deprecated": "Add `pod-install` to dependsOn for this target in project.json instead." }, "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add `sync-deps` to dependsOn for this target in project.json instead.", "default": true }, "resetCache": { diff --git a/packages/react-native/src/executors/start/start.impl.ts b/packages/react-native/src/executors/start/start.impl.ts index 8155da595bdeb4..7a956df8497e94 100644 --- a/packages/react-native/src/executors/start/start.impl.ts +++ b/packages/react-native/src/executors/start/start.impl.ts @@ -1,18 +1,15 @@ -import * as chalk from 'chalk'; import { ExecutorContext, logger } from '@nx/devkit'; import { ChildProcess, fork } from 'child_process'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; import { isPackagerRunning } from './lib/is-packager-running'; import { ReactNativeStartOptions } from './schema'; export interface ReactNativeStartOutput { - baseUrl?: string; + port?: number; success: boolean; } -let childProcess: ChildProcess; - export default async function* startExecutor( options: ReactNativeStartOptions, context: ExecutorContext @@ -21,27 +18,26 @@ export default async function* startExecutor( context.projectsConfigurations.projects[context.projectName].root; ensureNodeModulesSymlink(context.root, projectRoot); - try { - const baseUrl = `http://localhost:${options.port}`; - const appName = context.projectName; - logger.info(chalk.cyan(`Packager is ready at ${baseUrl}`)); - logger.info( - `Use ${chalk.bold(`nx run-android ${appName}`)} or ${chalk.bold( - `nx run-ios ${appName}` - )} to run the native app.` - ); + const startProcess = await runCliStart(context.root, projectRoot, options); - await runCliStart(context.root, projectRoot, options); + yield { + port: options.port, + success: true, + }; - yield { - baseUrl, - success: true, - }; - } finally { - if (childProcess) { - childProcess.kill(); - } + if (!startProcess) { + return; } + await new Promise((resolve) => { + const processExitListener = (signal?: number | NodeJS.Signals) => () => { + startProcess.kill(signal); + resolve(); + }; + process.on('exit', processExitListener); + process.on('SIGTERM', processExitListener); + process.on('SIGINT', processExitListener); + process.on('SIGQUIT', processExitListener); + }); } /* @@ -52,10 +48,10 @@ export async function runCliStart( workspaceRoot: string, projectRoot: string, options: ReactNativeStartOptions -): Promise { +): Promise { const result = await isPackagerRunning(options.port); if (result === 'running') { - logger.info('JS server already running.'); + logger.info(`JS server already running on port ${options.port}.`); } else if (result === 'unrecognized') { logger.warn('JS server not recognized.'); } else { @@ -63,7 +59,7 @@ export async function runCliStart( logger.info('Starting JS server...'); try { - await startAsync(workspaceRoot, projectRoot, options); + return await startAsync(workspaceRoot, projectRoot, options); } catch (error) { logger.error( `Failed to start the packager server. Error details: ${error.message}` @@ -77,24 +73,34 @@ function startAsync( workspaceRoot: string, projectRoot: string, options: ReactNativeStartOptions -): Promise { - return new Promise((resolve, reject) => { - childProcess = fork( - join(workspaceRoot, './node_modules/react-native/cli.js'), +): Promise { + return new Promise((resolve, reject) => { + const childProcess = fork( + require.resolve('react-native/cli.js'), ['start', ...createStartOptions(options)], - { cwd: join(workspaceRoot, projectRoot), env: process.env } + { + cwd: pathResolve(workspaceRoot, projectRoot), + env: process.env, + stdio: ['inherit', 'pipe', 'pipe', 'ipc'], + } ); - // Ensure the child process is killed when the parent exits - process.on('exit', () => childProcess.kill()); - process.on('SIGTERM', () => childProcess.kill()); + childProcess.stdout.on('data', (data) => { + process.stdout.write(data); + if (data.toString().includes('reload the app')) { + resolve(childProcess); + } + }); + childProcess.stderr.on('data', (data) => { + process.stderr.write(data); + }); childProcess.on('error', (err) => { reject(err); }); childProcess.on('exit', (code) => { if (code === 0) { - resolve(code); + resolve(childProcess); } else { reject(code); } diff --git a/packages/react-native/src/generators/application/application.ts b/packages/react-native/src/generators/application/application.ts index 2381112bae027e..fa5f0224cc71cd 100644 --- a/packages/react-native/src/generators/application/application.ts +++ b/packages/react-native/src/generators/application/application.ts @@ -7,7 +7,6 @@ import { Tree, } from '@nx/devkit'; -import { runPodInstall } from '../../utils/pod-install-task'; import { runSymlink } from '../../utils/symlink-task'; import { addLinting } from '../../utils/add-linting'; import { addJest } from '../../utils/add-jest'; @@ -48,10 +47,6 @@ export async function reactNativeApplicationGenerator( ); const detoxTask = await addDetox(host, options); const symlinkTask = runSymlink(host.root, options.appProjectRoot); - const podInstallTask = runPodInstall( - joinPathFragments(host.root, options.iosProjectRoot), - options.install - ); const chmodTaskGradlew = chmodAndroidGradlewFilesTask( joinPathFragments(host.root, options.androidProjectRoot) ); @@ -66,7 +61,6 @@ export async function reactNativeApplicationGenerator( jestTask, detoxTask, symlinkTask, - podInstallTask, chmodTaskGradlew ); } diff --git a/packages/react-native/src/generators/application/files/app/.ruby-version b/packages/react-native/src/generators/application/files/app/.ruby-version deleted file mode 100644 index 49cdd668e1c82b..00000000000000 --- a/packages/react-native/src/generators/application/files/app/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.7.6 diff --git a/packages/react-native/src/generators/application/files/app/Gemfile.template b/packages/react-native/src/generators/application/files/app/Gemfile.template index 567e59805c4a73..1fa2c2e1abdee6 100644 --- a/packages/react-native/src/generators/application/files/app/Gemfile.template +++ b/packages/react-native/src/generators/application/files/app/Gemfile.template @@ -1,6 +1,6 @@ source 'https://rubygems.org' # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version -ruby File.read(File.join(__dir__, '.ruby-version')).strip +ruby ">= 2.6.10" -gem 'cocoapods', '~> 1.11', '>= 1.11.3' +gem 'cocoapods', '~> 1.12' diff --git a/packages/react-native/src/generators/application/files/app/android/app/build.gradle.template b/packages/react-native/src/generators/application/files/app/android/app/build.gradle.template index 8ce7b1ab639de5..1fc5a2aeb56438 100644 --- a/packages/react-native/src/generators/application/files/app/android/app/build.gradle.template +++ b/packages/react-native/src/generators/application/files/app/android/app/build.gradle.template @@ -1,8 +1,6 @@ apply plugin: "com.android.application" apply plugin: "com.facebook.react" -import com.android.build.OutputFile - /** * This is the configuration block to customize your React Native Android app. * By default you don't need to apply any configuration, just uncomment the lines you need. @@ -13,8 +11,8 @@ react { // root = file("../") // The folder where the react-native NPM package is. Default is ../node_modules/react-native // reactNativeDir = file("../node_modules/react-native") - // The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen - // codegenDir = file("../node_modules/react-native-codegen") + // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen + // codegenDir = file("../node_modules/@react-native/codegen") // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js // cliFile = file("../node_modules/react-native/cli.js") @@ -53,14 +51,6 @@ react { entryFile = file("../../<%= entryFile %>") } -/** - * Set this to true to create four separate APKs instead of one, - * one for each native architecture. This is useful if you don't - * use App Bundles (https://developer.android.com/guide/app-bundle/) - * and want to have separate APKs to upload to the Play Store. - */ -def enableSeparateBuildPerCPUArchitecture = false - /** * Set this to true to Run Proguard on Release builds to minify the Java bytecode. */ @@ -79,16 +69,6 @@ def enableProguardInReleaseBuilds = false */ def jscFlavor = 'org.webkit:android-jsc:+' -/** - * Private function to get the list of Native Architectures you want to build. - * This reads the value from reactNativeArchitectures in your gradle.properties - * file and works together with the --active-arch-only flag of react-native run-android. - */ -def reactNativeArchitectures() { - def value = project.getProperties().get("reactNativeArchitectures") - return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] -} - android { ndkVersion rootProject.ext.ndkVersion @@ -106,15 +86,6 @@ android { testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' <% } %> } - - splits { - abi { - reset() - enable enableSeparateBuildPerCPUArchitecture - universalApk false // If true, also generate a universal APK - include (*reactNativeArchitectures()) - } - } signingConfigs { debug { storeFile file('debug.keystore') @@ -138,22 +109,6 @@ android { <% } %> } } - - // applicationVariants are e.g. debug, release - applicationVariants.all { variant -> - variant.outputs.each { output -> - // For each separate APK per architecture, set a unique version code as described here: - // https://developer.android.com/studio/build/configure-apk-splits.html - // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc. - def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] - def abi = output.getFilter(OutputFile.ABI) - if (abi != null) { // null for the universal-debug, universal-release variants - output.versionCodeOverride = - defaultConfig.versionCode * 1000 + versionCodes.get(abi) - } - - } - } } dependencies { @@ -164,8 +119,6 @@ dependencies { // The version of react-native is set by the React Native Gradle Plugin implementation("com.facebook.react:react-android") - implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0") - debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { exclude group:'com.squareup.okhttp3', module:'okhttp' diff --git a/packages/react-native/src/generators/application/files/app/android/app/src/main/java/com/__lowerCaseName__/MainActivity.java.template b/packages/react-native/src/generators/application/files/app/android/app/src/main/java/com/__lowerCaseName__/MainActivity.java.template index 629bff52ba19fc..981e6233377b76 100644 --- a/packages/react-native/src/generators/application/files/app/android/app/src/main/java/com/__lowerCaseName__/MainActivity.java.template +++ b/packages/react-native/src/generators/application/files/app/android/app/src/main/java/com/__lowerCaseName__/MainActivity.java.template @@ -1,4 +1,4 @@ -package com.<%= lowerCaseName %>; +package com.<%= className %>; import com.facebook.react.ReactActivity; import com.facebook.react.ReactActivityDelegate; @@ -27,9 +27,6 @@ public class MainActivity extends ReactActivity { this, getMainComponentName(), // If you opted-in for the New Architecture, we enable the Fabric Renderer. - DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled - // If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18). - DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled - ); + DefaultNewArchitectureEntryPoint.getFabricEnabled()); } } diff --git a/packages/react-native/src/generators/application/files/app/android/app/src/main/res/drawable/rn_edit_text_material.xml b/packages/react-native/src/generators/application/files/app/android/app/src/main/res/drawable/rn_edit_text_material.xml index f35d9962026a85..73b37e4d9963e2 100644 --- a/packages/react-native/src/generators/application/files/app/android/app/src/main/res/drawable/rn_edit_text_material.xml +++ b/packages/react-native/src/generators/application/files/app/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -20,7 +20,7 @@ android:insetBottom="@dimen/abc_edit_text_inset_bottom_material"> -