├── template ├── macos │ ├── .gitignore │ ├── Podfile.properties.json │ ├── HelloWorld-iOS │ │ ├── Images.xcassets │ │ │ ├── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── main.m │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Info.plist │ │ └── Base.lproj │ │ │ └── LaunchScreen.xib │ ├── HelloWorld-macOS │ │ ├── Assets.xcassets │ │ │ ├── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── ViewController.h │ │ ├── main.m │ │ ├── AppDelegate.h │ │ ├── HelloWorld.entitlements │ │ ├── ViewController.m │ │ ├── AppDelegate.m │ │ └── Info.plist │ ├── HelloWorld.xcworkspace │ │ └── contents.xcworkspacedata │ ├── Podfile │ └── HelloWorld.xcodeproj │ │ └── xcshareddata │ │ └── xcschemes │ │ ├── HelloWorld-iOS.xcscheme │ │ └── HelloWorld-macOS.xcscheme ├── windows │ ├── helloworld │ │ ├── _gitignore │ │ ├── pch.cpp │ │ ├── App.idl │ │ ├── Assets │ │ │ ├── StoreLogo.png │ │ │ ├── SplashScreen.scale-200.png │ │ │ ├── LockScreenLogo.scale-200.png │ │ │ ├── Square44x44Logo.scale-200.png │ │ │ ├── Wide310x150Logo.scale-200.png │ │ │ ├── Square150x150Logo.scale-200.png │ │ │ └── Square44x44Logo.targetsize-24_altform-unplated.png │ │ ├── MainPage.idl │ │ ├── AutolinkedNativeModules.g.targets │ │ ├── AutolinkedNativeModules.g.props │ │ ├── AutolinkedNativeModules.g.h │ │ ├── MainPage.h │ │ ├── ReactPackageProvider.cpp │ │ ├── App.xaml │ │ ├── MainPage.cpp │ │ ├── ReactPackageProvider.h │ │ ├── AutolinkedNativeModules.g.cpp │ │ ├── PropertySheet.props │ │ ├── MainPage.xaml │ │ ├── App.h │ │ ├── pch.h │ │ ├── Package.appxmanifest │ │ ├── helloworld.vcxproj.filters │ │ ├── App.cpp │ │ └── helloworld.vcxproj │ ├── NuGet.Config │ ├── .gitignore │ ├── ExperimentalFeatures.props │ └── helloworld.sln ├── ios │ ├── Podfile.properties.json │ ├── HelloWorld │ │ ├── Images.xcassets │ │ │ ├── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── AppDelegate.h │ │ ├── main.m │ │ ├── Supporting │ │ │ └── Expo.plist │ │ ├── AppDelegate.mm │ │ ├── Info.plist │ │ └── LaunchScreen.storyboard │ ├── HelloWorld.xcworkspace │ │ └── contents.xcworkspacedata │ ├── HelloWorldTests │ │ ├── Info.plist │ │ └── HelloWorldTests.m │ ├── Podfile │ └── HelloWorld.xcodeproj │ │ └── xcshareddata │ │ └── xcschemes │ │ └── HelloWorld.xcscheme ├── tsconfig.json ├── babel.config.js ├── android │ ├── app │ │ ├── debug.keystore │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── values │ │ │ │ │ │ ├── strings.xml │ │ │ │ │ │ └── styles.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ └── drawable │ │ │ │ │ │ └── rn_edit_text_material.xml │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── helloworld │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MainApplication.java │ │ │ ├── debug │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── helloworld │ │ │ │ │ └── ReactNativeFlipper.java │ │ │ └── release │ │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── helloworld │ │ │ │ └── ReactNativeFlipper.java │ │ ├── proguard-rules.pro │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ ├── build.gradle │ ├── gradle.properties │ ├── gradlew.bat │ └── gradlew ├── plugins │ ├── expo-cli-670287b.tgz │ ├── expo-config-plugins-670287b.tgz │ ├── _utils │ │ ├── serialization.js │ │ ├── platforms.js │ │ └── files.js │ ├── macos │ │ ├── withMacOS.js │ │ ├── withWindowSize.js │ │ └── base.js │ ├── windows │ │ ├── withWindows.js │ │ ├── withNuGetSources.js │ │ ├── withExperimentalFeatures.js │ │ └── base.js │ ├── android │ │ └── withoutExpoSplashScreen.js │ └── universal │ │ └── withJsEngine.js ├── index.js ├── Gemfile ├── react-native.config.js ├── app.json ├── metro.config.js ├── gitignore ├── package.json └── App.tsx ├── app ├── .bundle │ └── config ├── tsconfig.json ├── babel.config.js ├── plugins │ ├── expo-cli-670287b.tgz │ ├── expo-config-plugins-670287b.tgz │ ├── _utils │ │ ├── serialization.js │ │ ├── platforms.js │ │ └── files.js │ ├── macos │ │ ├── withMacOS.js │ │ ├── withWindowSize.js │ │ └── base.js │ ├── windows │ │ ├── withWindows.js │ │ ├── withNuGetSources.js │ │ ├── withExperimentalFeatures.js │ │ └── base.js │ ├── android │ │ └── withoutExpoSplashScreen.js │ └── universal │ │ └── withJsEngine.js ├── index.js ├── Gemfile ├── __tests__ │ └── App-test.js ├── react-native.config.js ├── app.json ├── .gitignore ├── metro.config.js ├── package.json ├── Gemfile.lock └── App.tsx └── README.md /template/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # CocoaPods 2 | Pods/ 3 | -------------------------------------------------------------------------------- /template/windows/helloworld/_gitignore: -------------------------------------------------------------------------------- 1 | /Bundle 2 | -------------------------------------------------------------------------------- /template/windows/helloworld/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /template/windows/helloworld/App.idl: -------------------------------------------------------------------------------- 1 | namespace helloworld 2 | { 3 | } 4 | -------------------------------------------------------------------------------- /template/ios/Podfile.properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo.jsEngine": "jsc" 3 | } 4 | -------------------------------------------------------------------------------- /template/macos/Podfile.properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo.jsEngine": "jsc" 3 | } 4 | -------------------------------------------------------------------------------- /app/.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/react-native/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /template/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/react-native/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /app/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /template/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /app/plugins/expo-cli-670287b.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/app/plugins/expo-cli-670287b.tgz -------------------------------------------------------------------------------- /template/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/android/app/debug.keystore -------------------------------------------------------------------------------- /template/ios/HelloWorld/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /template/plugins/expo-cli-670287b.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/plugins/expo-cli-670287b.tgz -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | import {AppRegistry} from 'react-native'; 2 | import App from './App'; 3 | 4 | AppRegistry.registerComponent('main', () => App); 5 | -------------------------------------------------------------------------------- /template/macos/HelloWorld-iOS/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /template/macos/HelloWorld-macOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /template/macos/HelloWorld-macOS/ViewController.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface ViewController : NSViewController 4 | 5 | @end 6 | -------------------------------------------------------------------------------- /template/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Hello App Display Name 3 | 4 | -------------------------------------------------------------------------------- /template/index.js: -------------------------------------------------------------------------------- 1 | import {AppRegistry} from 'react-native'; 2 | import App from './App'; 3 | 4 | AppRegistry.registerComponent('main', () => App); 5 | -------------------------------------------------------------------------------- /app/plugins/expo-config-plugins-670287b.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/app/plugins/expo-config-plugins-670287b.tgz -------------------------------------------------------------------------------- /template/ios/HelloWorld/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : RCTAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /template/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /template/macos/HelloWorld-macOS/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | int main(int argc, const char *argv[]) { 4 | return NSApplicationMain(argc, argv); 5 | } 6 | -------------------------------------------------------------------------------- /template/plugins/expo-config-plugins-670287b.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/plugins/expo-config-plugins-670287b.tgz -------------------------------------------------------------------------------- /template/windows/helloworld/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/windows/helloworld/Assets/StoreLogo.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /template/windows/helloworld/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/windows/helloworld/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /app/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby ">= 2.6.10" 5 | 6 | gem 'cocoapods', '~> 1.12' 7 | -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /template/windows/helloworld/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/windows/helloworld/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /template/windows/helloworld/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/windows/helloworld/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /template/windows/helloworld/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/windows/helloworld/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /app/plugins/_utils/serialization.js: -------------------------------------------------------------------------------- 1 | const XML = require('@expo/config-plugins/build/utils/XML'); 2 | 3 | module.exports = { 4 | parseXml: XML.parseXMLAsync, 5 | stringifyXml: XML.format, 6 | }; 7 | -------------------------------------------------------------------------------- /template/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby ">= 2.6.10" 5 | 6 | gem 'cocoapods', '~> 1.12' 7 | -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /template/windows/helloworld/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/windows/helloworld/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /template/plugins/_utils/serialization.js: -------------------------------------------------------------------------------- 1 | const XML = require('@expo/config-plugins/build/utils/XML'); 2 | 3 | module.exports = { 4 | parseXml: XML.parseXMLAsync, 5 | stringifyXml: XML.format, 6 | }; 7 | -------------------------------------------------------------------------------- /app/plugins/macos/withMacOS.js: -------------------------------------------------------------------------------- 1 | const { withMacOSBaseMod } = require('./base'); 2 | 3 | // Export the base mod, note that this has to be the LAST plugin in the plugins list. 4 | module.exports = withMacOSBaseMod; 5 | -------------------------------------------------------------------------------- /template/plugins/macos/withMacOS.js: -------------------------------------------------------------------------------- 1 | const { withMacOSBaseMod } = require('./base'); 2 | 3 | // Export the base mod, note that this has to be the LAST plugin in the plugins list. 4 | module.exports = withMacOSBaseMod; 5 | -------------------------------------------------------------------------------- /app/plugins/windows/withWindows.js: -------------------------------------------------------------------------------- 1 | const { withWindowsBaseMod } = require('./base'); 2 | 3 | // Export the base mod, note that this has to be the LAST plugin in the plugins list. 4 | module.exports = withWindowsBaseMod; 5 | -------------------------------------------------------------------------------- /template/plugins/windows/withWindows.js: -------------------------------------------------------------------------------- 1 | const { withWindowsBaseMod } = require('./base'); 2 | 3 | // Export the base mod, note that this has to be the LAST plugin in the plugins list. 4 | module.exports = withWindowsBaseMod; 5 | -------------------------------------------------------------------------------- /template/windows/helloworld/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byCedric/custom-prebuild-example/HEAD/template/windows/helloworld/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /template/macos/HelloWorld-macOS/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class RCTBridge; 4 | 5 | @interface AppDelegate : NSObject 6 | 7 | @property (nonatomic, readonly) RCTBridge *bridge; 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /template/windows/helloworld/MainPage.idl: -------------------------------------------------------------------------------- 1 | #include "NamespaceRedirect.h" 2 | 3 | namespace helloworld 4 | { 5 | [default_interface] 6 | runtimeclass MainPage : XAML_NAMESPACE.Controls.Page 7 | { 8 | MainPage(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /template/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /template/ios/HelloWorld/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | @autoreleasepool { 8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /template/macos/HelloWorld-iOS/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /template/macos/HelloWorld-iOS/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import // [macOS] 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (nonatomic, strong) UIWindow *window; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /template/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'HelloWorld' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | includeBuild('../node_modules/react-native-gradle-plugin') 5 | -------------------------------------------------------------------------------- /template/windows/helloworld/AutolinkedNativeModules.g.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /template/windows/helloworld/AutolinkedNativeModules.g.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /template/ios/HelloWorld.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /template/macos/HelloWorld.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/__tests__/App-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../App'; 8 | 9 | // Note: test renderer must be required after react-native. 10 | import renderer from 'react-test-renderer'; 11 | 12 | it('renders correctly', () => { 13 | renderer.create(); 14 | }); 15 | -------------------------------------------------------------------------------- /template/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /template/ios/HelloWorld/Supporting/Expo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | EXUpdatesSDKVersion 6 | YOUR-APP-SDK-VERSION-HERE 7 | EXUpdatesURL 8 | YOUR-APP-URL-HERE 9 | 10 | 11 | -------------------------------------------------------------------------------- /template/windows/NuGet.Config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/react-native.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | dependencies: { 3 | // Just for demonstration purposes: a React Native app, without any Expo native code... 4 | // _While still leveraging Expo Prebuild and Expo Config Plugins, using an out-of-tree platform._ 5 | expo: { 6 | platforms: { 7 | android: null, 8 | ios: null, 9 | macos: null, 10 | }, 11 | }, 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /template/react-native.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | dependencies: { 3 | // Just for demonstration purposes: a React Native app, without any Expo native code... 4 | // _While still leveraging Expo Prebuild and Expo Config Plugins, using an out-of-tree platform._ 5 | expo: { 6 | platforms: { 7 | android: null, 8 | ios: null, 9 | macos: null, 10 | }, 11 | }, 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /template/windows/helloworld/AutolinkedNativeModules.g.h: -------------------------------------------------------------------------------- 1 | // AutolinkedNativeModules.g.h contents generated by "react-native autolink-windows" 2 | // clang-format off 3 | #pragma once 4 | 5 | namespace winrt::Microsoft::ReactNative 6 | { 7 | 8 | void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /template/windows/helloworld/MainPage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MainPage.g.h" 3 | #include 4 | 5 | namespace winrt::helloworld::implementation 6 | { 7 | struct MainPage : MainPageT 8 | { 9 | MainPage(); 10 | }; 11 | } 12 | 13 | namespace winrt::helloworld::factory_implementation 14 | { 15 | struct MainPage : MainPageT 16 | { 17 | }; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /template/macos/HelloWorld-macOS/HelloWorld.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | com.apple.security.network.client 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /template/windows/helloworld/ReactPackageProvider.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ReactPackageProvider.h" 3 | #include "NativeModules.h" 4 | 5 | using namespace winrt::Microsoft::ReactNative; 6 | 7 | namespace winrt::helloworld::implementation 8 | { 9 | 10 | void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept 11 | { 12 | AddAttributedModules(packageBuilder, true); 13 | } 14 | 15 | } // namespace winrt::helloworld::implementation 16 | -------------------------------------------------------------------------------- /template/windows/helloworld/App.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /template/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /template/windows/helloworld/MainPage.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "MainPage.h" 3 | #if __has_include("MainPage.g.cpp") 4 | #include "MainPage.g.cpp" 5 | #endif 6 | 7 | #include "App.h" 8 | 9 | using namespace winrt; 10 | using namespace xaml; 11 | 12 | namespace winrt::helloworld::implementation 13 | { 14 | MainPage::MainPage() 15 | { 16 | InitializeComponent(); 17 | auto app = Application::Current().as(); 18 | ReactRootView().ReactNativeHost(app->Host()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /template/windows/helloworld/ReactPackageProvider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "winrt/Microsoft.ReactNative.h" 4 | 5 | namespace winrt::helloworld::implementation 6 | { 7 | struct ReactPackageProvider : winrt::implements 8 | { 9 | public: // IReactPackageProvider 10 | void CreatePackage(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept; 11 | }; 12 | } // namespace winrt::helloworld::implementation 13 | 14 | -------------------------------------------------------------------------------- /template/windows/helloworld/AutolinkedNativeModules.g.cpp: -------------------------------------------------------------------------------- 1 | // AutolinkedNativeModules.g.cpp contents generated by "react-native autolink-windows" 2 | // clang-format off 3 | #include "pch.h" 4 | #include "AutolinkedNativeModules.g.h" 5 | 6 | namespace winrt::Microsoft::ReactNative 7 | { 8 | 9 | void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders) 10 | { 11 | UNREFERENCED_PARAMETER(packageProviders); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /template/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /template/windows/helloworld/PropertySheet.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /template/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = "33.0.0" 6 | minSdkVersion = 21 7 | compileSdkVersion = 33 8 | targetSdkVersion = 33 9 | 10 | // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP. 11 | ndkVersion = "23.1.7779620" 12 | } 13 | repositories { 14 | google() 15 | mavenCentral() 16 | } 17 | dependencies { 18 | classpath("com.android.tools.build:gradle:7.3.1") 19 | classpath("com.facebook.react:react-native-gradle-plugin") 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /template/windows/helloworld/MainPage.xaml: -------------------------------------------------------------------------------- 1 | 11 | 16 | 17 | -------------------------------------------------------------------------------- /template/macos/HelloWorld-macOS/ViewController.m: -------------------------------------------------------------------------------- 1 | #import "ViewController.h" 2 | #import "AppDelegate.h" 3 | 4 | #import 5 | 6 | @implementation ViewController 7 | 8 | - (void)viewDidLoad { 9 | [super viewDidLoad]; 10 | 11 | RCTBridge *bridge = [((AppDelegate *)[NSApp delegate])bridge]; 12 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"main" initialProperties:nil]; 13 | 14 | NSView *view = [self view]; 15 | 16 | [view addSubview:rootView]; 17 | [rootView setBackgroundColor:[NSColor windowBackgroundColor]]; 18 | [rootView setFrame:[view bounds]]; 19 | [rootView setAutoresizingMask:(NSViewMinXMargin | NSViewMaxXMargin | NSViewMinYMargin | NSViewMaxYMargin | NSViewWidthSizable | NSViewHeightSizable)]; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /template/macos/HelloWorld-iOS/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /template/android/app/src/release/java/com/helloworld/ReactNativeFlipper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | *

This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | package com.helloworld; 8 | 9 | import android.content.Context; 10 | import com.facebook.react.ReactInstanceManager; 11 | 12 | /** 13 | * Class responsible of loading Flipper inside your React Native application. This is the release 14 | * flavor of it so it's empty as we don't want to load Flipper. 15 | */ 16 | public class ReactNativeFlipper { 17 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 18 | // Do nothing as we don't want to initialize Flipper on Release. 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /template/windows/helloworld/App.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "App.xaml.g.h" 4 | 5 | #include 6 | 7 | namespace activation = winrt::Windows::ApplicationModel::Activation; 8 | 9 | namespace winrt::helloworld::implementation 10 | { 11 | struct App : AppT 12 | { 13 | App() noexcept; 14 | void OnLaunched(activation::LaunchActivatedEventArgs const&); 15 | void OnActivated(Windows::ApplicationModel::Activation::IActivatedEventArgs const &e); 16 | void OnSuspending(IInspectable const&, Windows::ApplicationModel::SuspendingEventArgs const&); 17 | void OnNavigationFailed(IInspectable const&, xaml::Navigation::NavigationFailedEventArgs const&); 18 | private: 19 | using super = AppT; 20 | }; 21 | } // namespace winrt::helloworld::implementation 22 | -------------------------------------------------------------------------------- /template/windows/helloworld/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define NOMINMAX 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | using namespace winrt::Windows::Foundation; 25 | -------------------------------------------------------------------------------- /template/ios/HelloWorldTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /template/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CustomPrebuildExample", 3 | "displayName": "CustomPrebuildExample", 4 | "expo": { 5 | "name": "CustomPrebuildExample", 6 | "slug": "custom-prebuild-example", 7 | "plugins": [ 8 | "./plugins/android/withoutExpoSplashScreen", 9 | [ 10 | "./plugins/macos/withWindowSize", 11 | { 12 | "width": 800, 13 | "height": 600 14 | } 15 | ], 16 | [ 17 | "./plugins/windows/withExperimentalFeatures", 18 | { 19 | "useHermes": true 20 | } 21 | ], 22 | [ 23 | "./plugins/windows/withNuGetSources", 24 | { 25 | "packageSources": { 26 | "Nuget.org": "https://api.nuget.org/v3/index.json" 27 | } 28 | } 29 | ], 30 | "./plugins/macos/withMacOS", 31 | "./plugins/windows/withWindows" 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /template/macos/HelloWorld-macOS/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | #import 5 | 6 | @interface AppDelegate () 7 | 8 | @end 9 | 10 | @implementation AppDelegate 11 | 12 | - (void)awakeFromNib { 13 | [super awakeFromNib]; 14 | 15 | _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil]; 16 | } 17 | 18 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 19 | // Insert code here to initialize your application 20 | } 21 | 22 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 23 | // Insert code here to tear down your application 24 | } 25 | 26 | #pragma mark - RCTBridgeDelegate Methods 27 | 28 | - (NSURL *)sourceURLForBridge:(__unused RCTBridge *)bridge { 29 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; // .jsbundle; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /app/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CustomPrebuildExample", 3 | "displayName": "CustomPrebuildExample", 4 | "expo": { 5 | "name": "CustomPrebuildExample", 6 | "slug": "custom-prebuild-example", 7 | "plugins": [ 8 | "./plugins/android/withoutExpoSplashScreen", 9 | ["./plugins/universal/withJsEngine.js", { "engine": "hermes" }], 10 | [ 11 | "./plugins/macos/withWindowSize", 12 | { 13 | "width": 800, 14 | "height": 600 15 | } 16 | ], 17 | [ 18 | "./plugins/windows/withNuGetSources", 19 | { 20 | "packageSources": { 21 | "Nuget.org": "https://api.nuget.org/v3/index.json" 22 | } 23 | } 24 | ], 25 | "./plugins/macos/withMacOS", 26 | "./plugins/windows/withWindows" 27 | ], 28 | "android": { 29 | "package": "com.bycedric.customprebuildexample" 30 | }, 31 | "ios": { 32 | "bundleIdentifier": "com.bycedric.customprebuildexample" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/plugins/android/withoutExpoSplashScreen.js: -------------------------------------------------------------------------------- 1 | const {withAndroidStyles, createRunOncePlugin} = require('expo/config-plugins'); 2 | 3 | /** Disable the default Android changes in react native apps */ 4 | function withoutExpoSplashScreen(c) { 5 | return withAndroidStyles(c, config => { 6 | // Filter out the default Expo styles 7 | config.modResults.resources.style = 8 | config.modResults.resources.style.filter( 9 | style => !isExpoAppTheme(style) && !isExpoSplashScreen(style), 10 | ); 11 | 12 | return config; 13 | }); 14 | } 15 | 16 | function isExpoAppTheme(style) { 17 | return ( 18 | style.$?.name === 'AppTheme' && 19 | style.$?.parent === 'Theme.AppCompat.Light.NoActionBar' 20 | ); 21 | } 22 | 23 | function isExpoSplashScreen(style) { 24 | return ( 25 | style.$?.name === 'Theme.App.SplashScreen' && style.$?.parent === 'AppTheme' 26 | ); 27 | } 28 | 29 | module.exports = createRunOncePlugin( 30 | withoutExpoSplashScreen, 31 | 'withoutExpoSplashScreen', 32 | '1.0.0', 33 | ); 34 | -------------------------------------------------------------------------------- /template/plugins/android/withoutExpoSplashScreen.js: -------------------------------------------------------------------------------- 1 | const {withAndroidStyles, createRunOncePlugin} = require('expo/config-plugins'); 2 | 3 | /** Disable the default Android changes in react native apps */ 4 | function withoutExpoSplashScreen(c) { 5 | return withAndroidStyles(c, config => { 6 | // Filter out the default Expo styles 7 | config.modResults.resources.style = 8 | config.modResults.resources.style.filter( 9 | style => !isExpoAppTheme(style) && !isExpoSplashScreen(style), 10 | ); 11 | 12 | return config; 13 | }); 14 | } 15 | 16 | function isExpoAppTheme(style) { 17 | return ( 18 | style.$?.name === 'AppTheme' && 19 | style.$?.parent === 'Theme.AppCompat.Light.NoActionBar' 20 | ); 21 | } 22 | 23 | function isExpoSplashScreen(style) { 24 | return ( 25 | style.$?.name === 'Theme.App.SplashScreen' && style.$?.parent === 'AppTheme' 26 | ); 27 | } 28 | 29 | module.exports = createRunOncePlugin( 30 | withoutExpoSplashScreen, 31 | 'withoutExpoSplashScreen', 32 | '1.0.0', 33 | ); 34 | -------------------------------------------------------------------------------- /app/plugins/macos/withWindowSize.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const {createRunOncePlugin} = require('expo/config-plugins'); 3 | const {withMacOSViewController} = require('./base'); 4 | 5 | const INSERT_PATTERN = 'NSView *view = [self view];'; 6 | 7 | /** 8 | * This plugin adds `[view setFrameSize:...]` that should set the initial screen size of a macos app. 9 | * @type {import('@expo/config-plugins').ConfigPlugin} 10 | */ 11 | function withWindowSize(c, {width = 800, height = 600} = {}) { 12 | return withMacOSViewController(c, config => { 13 | assert(config.modResults.language === 'objc', 'View controller must be Objective-C to use withViewSize.'); 14 | 15 | const insertText = `[view setFrameSize:NSMakeSize(${width}, ${height})];`; 16 | 17 | config.modResults.contents = config.modResults.contents.replace( 18 | INSERT_PATTERN, 19 | `${INSERT_PATTERN}\n ${insertText}`, 20 | ); 21 | 22 | return config; 23 | }); 24 | } 25 | 26 | module.exports = createRunOncePlugin(withWindowSize, 'withWindowSize', '1.0.0'); 27 | -------------------------------------------------------------------------------- /template/plugins/macos/withWindowSize.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const {createRunOncePlugin} = require('expo/config-plugins'); 3 | const {withMacOSViewController} = require('./base'); 4 | 5 | const INSERT_PATTERN = 'NSView *view = [self view];'; 6 | 7 | /** 8 | * This plugin adds `[view setFrameSize:...]` that should set the initial screen size of a macos app. 9 | * @type {import('@expo/config-plugins').ConfigPlugin} 10 | */ 11 | function withWindowSize(c, {width = 800, height = 600} = {}) { 12 | return withMacOSViewController(c, config => { 13 | assert(config.modResults.language === 'objc', 'View controller must be Objective-C to use withViewSize.'); 14 | 15 | const insertText = `[view setFrameSize:NSMakeSize(${width}, ${height})];`; 16 | 17 | config.modResults.contents = config.modResults.contents.replace( 18 | INSERT_PATTERN, 19 | `${INSERT_PATTERN}\n ${insertText}`, 20 | ); 21 | 22 | return config; 23 | }); 24 | } 25 | 26 | module.exports = createRunOncePlugin(withWindowSize, 'withWindowSize', '1.0.0'); 27 | -------------------------------------------------------------------------------- /template/metro.config.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const exclusionList = require('metro-config/src/defaults/exclusionList'); 4 | 5 | const rnwPath = fs.realpathSync(path.resolve(require.resolve('react-native-windows/package.json'), '..')); 6 | 7 | module.exports = { 8 | resolver: { 9 | blockList: exclusionList([ 10 | // This stops "react-native run-windows" from causing the metro server to crash if its already running 11 | new RegExp(`${path.resolve(__dirname, 'windows').replace(/[/\\]/g, '/')}.*`), 12 | // This prevents "react-native run-windows" from hitting: EBUSY: resource busy or locked, open msbuild.ProjectImports.zip or other files produced by msbuild 13 | new RegExp(`${rnwPath}/build/.*`), 14 | new RegExp(`${rnwPath}/target/.*`), 15 | /.*\.ProjectImports\.zip/, 16 | ]), 17 | }, 18 | transformer: { 19 | getTransformOptions: async () => ({ 20 | transform: { 21 | experimentalImportSupport: false, 22 | inlineRequires: true, 23 | }, 24 | }), 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /template/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /template/ios/HelloWorld/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "scale" : "1x", 46 | "size" : "1024x1024" 47 | } 48 | ], 49 | "info" : { 50 | "author" : "xcode", 51 | "version" : 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /template/gitignore: -------------------------------------------------------------------------------- 1 | # Prebuild 2 | /.expo 3 | /android 4 | /ios 5 | /macos 6 | /windows 7 | 8 | # OSX 9 | # 10 | .DS_Store 11 | 12 | # Xcode 13 | # 14 | build/ 15 | *.pbxuser 16 | !default.pbxuser 17 | *.mode1v3 18 | !default.mode1v3 19 | *.mode2v3 20 | !default.mode2v3 21 | *.perspectivev3 22 | !default.perspectivev3 23 | xcuserdata 24 | *.xccheckout 25 | *.moved-aside 26 | DerivedData 27 | *.hmap 28 | *.ipa 29 | *.xcuserstate 30 | 31 | # Android/IntelliJ 32 | # 33 | build/ 34 | .idea 35 | .gradle 36 | local.properties 37 | *.iml 38 | *.hprof 39 | 40 | # node.js 41 | # 42 | node_modules/ 43 | npm-debug.log 44 | yarn-error.log 45 | 46 | # BUCK 47 | buck-out/ 48 | \.buckd/ 49 | *.keystore 50 | !debug.keystore 51 | 52 | # fastlane 53 | # 54 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 55 | # screenshots whenever they are needed. 56 | # For more information about the recommended setup visit: 57 | # https://docs.fastlane.tools/best-practices/source-control/ 58 | 59 | */fastlane/report.xml 60 | */fastlane/Preview.html 61 | */fastlane/screenshots 62 | 63 | # Bundle artifact 64 | *.jsbundle 65 | 66 | # Ruby / CocoaPods 67 | /ios/Pods/ 68 | /vendor/bundle/ 69 | -------------------------------------------------------------------------------- /template/macos/HelloWorld-macOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "scale" : "1x", 6 | "size" : "16x16" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "scale" : "2x", 11 | "size" : "16x16" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "scale" : "1x", 16 | "size" : "32x32" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "scale" : "2x", 21 | "size" : "32x32" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "scale" : "1x", 26 | "size" : "128x128" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "scale" : "2x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "scale" : "1x", 36 | "size" : "256x256" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "scale" : "2x", 41 | "size" : "256x256" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "scale" : "1x", 46 | "size" : "512x512" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "scale" : "2x", 51 | "size" : "512x512" 52 | } 53 | ], 54 | "info" : { 55 | "author" : "xcode", 56 | "version" : 1 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | # Prebuild 2 | /.expo 3 | /android 4 | /ios 5 | /macos 6 | /windows 7 | 8 | # Windows 9 | msbuild.binlog 10 | 11 | # OSX 12 | # 13 | .DS_Store 14 | 15 | # Xcode 16 | # 17 | build/ 18 | *.pbxuser 19 | !default.pbxuser 20 | *.mode1v3 21 | !default.mode1v3 22 | *.mode2v3 23 | !default.mode2v3 24 | *.perspectivev3 25 | !default.perspectivev3 26 | xcuserdata 27 | *.xccheckout 28 | *.moved-aside 29 | DerivedData 30 | *.hmap 31 | *.ipa 32 | *.xcuserstate 33 | 34 | # Android/IntelliJ 35 | # 36 | build/ 37 | .idea 38 | .gradle 39 | local.properties 40 | *.iml 41 | *.hprof 42 | 43 | # node.js 44 | # 45 | node_modules/ 46 | npm-debug.log 47 | yarn-error.log 48 | 49 | # BUCK 50 | buck-out/ 51 | \.buckd/ 52 | *.keystore 53 | !debug.keystore 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://docs.fastlane.tools/best-practices/source-control/ 61 | 62 | */fastlane/report.xml 63 | */fastlane/Preview.html 64 | */fastlane/screenshots 65 | 66 | # Bundle artifact 67 | *.jsbundle 68 | 69 | # Ruby / CocoaPods 70 | /ios/Pods/ 71 | /vendor/bundle/ 72 | -------------------------------------------------------------------------------- /app/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | const fs = require('fs'); 8 | const path = require('path'); 9 | const exclusionList = require('metro-config/src/defaults/exclusionList'); 10 | 11 | const rnwPath = fs.realpathSync( 12 | path.resolve(require.resolve('react-native-windows/package.json'), '..'), 13 | ); 14 | 15 | module.exports = { 16 | resolver: { 17 | blockList: exclusionList([ 18 | // This stops "react-native run-windows" from causing the metro server to crash if its already running 19 | new RegExp( 20 | `${path.resolve(__dirname, 'windows').replace(/[/\\]/g, '/')}.*`, 21 | ), 22 | // This prevents "react-native run-windows" from hitting: EBUSY: resource busy or locked, open msbuild.ProjectImports.zip or other files produced by msbuild 23 | new RegExp(`${rnwPath}/build/.*`), 24 | new RegExp(`${rnwPath}/target/.*`), 25 | /.*\.ProjectImports\.zip/, 26 | ]), 27 | }, 28 | transformer: { 29 | getTransformOptions: async () => ({ 30 | transform: { 31 | experimentalImportSupport: false, 32 | inlineRequires: true, 33 | }, 34 | }), 35 | }, 36 | }; 37 | -------------------------------------------------------------------------------- /template/ios/HelloWorld/AppDelegate.mm: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | 5 | @implementation AppDelegate 6 | 7 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 8 | { 9 | self.moduleName = @"main"; 10 | // You can add your custom initial props in the dictionary below. 11 | // They will be passed down to the ViewController used by React Native. 12 | self.initialProps = @{}; 13 | 14 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 15 | } 16 | 17 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 18 | { 19 | #if DEBUG 20 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; 21 | #else 22 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 23 | #endif 24 | } 25 | 26 | /// This method controls whether the `concurrentRoot`feature of React18 is turned on or off. 27 | /// 28 | /// @see: https://reactjs.org/blog/2022/03/29/react-v18.html 29 | /// @note: This requires to be rendering on Fabric (i.e. on the New Architecture). 30 | /// @return: `true` if the `concurrentRoot` feature is enabled. Otherwise, it returns `false`. 31 | - (BOOL)concurrentRootEnabled 32 | { 33 | return true; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /template/windows/.gitignore: -------------------------------------------------------------------------------- 1 | *AppPackages* 2 | *BundleArtifacts* 3 | 4 | #OS junk files 5 | [Tt]humbs.db 6 | *.DS_Store 7 | 8 | #Visual Studio files 9 | *.[Oo]bj 10 | *.user 11 | *.aps 12 | *.pch 13 | *.vspscc 14 | *.vssscc 15 | *_i.c 16 | *_p.c 17 | *.ncb 18 | *.suo 19 | *.tlb 20 | *.tlh 21 | *.bak 22 | *.[Cc]ache 23 | *.ilk 24 | *.log 25 | *.lib 26 | *.sbr 27 | *.sdf 28 | *.opensdf 29 | *.opendb 30 | *.unsuccessfulbuild 31 | ipch/ 32 | [Oo]bj/ 33 | [Bb]in 34 | [Dd]ebug*/ 35 | [Rr]elease*/ 36 | Ankh.NoLoad 37 | 38 | # Visual C++ cache files 39 | ipch/ 40 | *.aps 41 | *.ncb 42 | *.opendb 43 | *.opensdf 44 | *.sdf 45 | *.cachefile 46 | *.VC.db 47 | *.VC.VC.opendb 48 | 49 | #MonoDevelop 50 | *.pidb 51 | *.userprefs 52 | 53 | #Tooling 54 | _ReSharper*/ 55 | *.resharper 56 | [Tt]est[Rr]esult* 57 | *.sass-cache 58 | 59 | #Project files 60 | [Bb]uild/ 61 | 62 | #Subversion files 63 | .svn 64 | 65 | # Office Temp Files 66 | ~$* 67 | 68 | # vim Temp Files 69 | *~ 70 | 71 | #NuGet 72 | packages/ 73 | *.nupkg 74 | 75 | #ncrunch 76 | *ncrunch* 77 | *crunch*.local.xml 78 | 79 | # visual studio database projects 80 | *.dbmdl 81 | 82 | #Test files 83 | *.testsettings 84 | 85 | #Other files 86 | *.DotSettings 87 | .vs/ 88 | *project.lock.json 89 | 90 | #Files generated by the VS build 91 | **/Generated Files/** 92 | 93 | -------------------------------------------------------------------------------- /template/macos/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../node_modules/react-native-macos/scripts/react_native_pods' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | require 'json' 5 | podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {} 6 | 7 | target 'HelloWorld-macOS' do 8 | platform :macos, '10.15' 9 | use_native_modules! 10 | use_react_native!( 11 | :path => '../node_modules/react-native-macos', 12 | # to enable hermes on macOS, change `false` to `true` and then install pods 13 | :hermes_enabled => podfile_properties['expo.jsEngine'] == nil || podfile_properties['expo.jsEngine'] == 'hermes' 14 | ) 15 | 16 | # Pods specifically for macOS target 17 | end 18 | 19 | target 'HelloWorld-iOS' do 20 | platform :ios, '12.4' 21 | use_native_modules! 22 | use_react_native!(:path => '../node_modules/react-native-macos') 23 | 24 | # Enables Flipper. 25 | # 26 | # Note that if you have use_frameworks! enabled, Flipper will not work and 27 | # you should disable these next few lines. 28 | use_flipper! 29 | 30 | post_install do |installer| 31 | react_native_post_install(installer) 32 | __apply_Xcode_12_5_M1_post_install_workaround(installer) 33 | end 34 | # Pods specifically for iOS target 35 | end 36 | -------------------------------------------------------------------------------- /template/macos/HelloWorld-iOS/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | #import 5 | #import 6 | 7 | @implementation AppDelegate 8 | 9 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 10 | { 11 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 12 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 13 | moduleName:@"main" 14 | initialProperties:nil]; 15 | 16 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 17 | 18 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 19 | UIViewController *rootViewController = [UIViewController new]; 20 | rootViewController.view = rootView; 21 | self.window.rootViewController = rootViewController; 22 | [self.window makeKeyAndVisible]; 23 | return YES; 24 | } 25 | 26 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 27 | { 28 | #if DEBUG 29 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; 30 | #else 31 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 32 | #endif 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /template/windows/ExperimentalFeatures.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | 17 | false 18 | 19 | 25 | false 26 | 27 | 34 | false 35 | 36 | true 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /template/android/app/src/main/java/com/helloworld/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.helloworld; 2 | 3 | import com.facebook.react.ReactActivity; 4 | import com.facebook.react.ReactActivityDelegate; 5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; 6 | import com.facebook.react.defaults.DefaultReactActivityDelegate; 7 | 8 | public class MainActivity extends ReactActivity { 9 | 10 | /** 11 | * Returns the name of the main component registered from JavaScript. This is used to schedule 12 | * rendering of the component. 13 | */ 14 | @Override 15 | protected String getMainComponentName() { 16 | return "main"; 17 | } 18 | 19 | /** 20 | * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link 21 | * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React 22 | * (aka React 18) with two boolean flags. 23 | */ 24 | @Override 25 | protected ReactActivityDelegate createReactActivityDelegate() { 26 | return new DefaultReactActivityDelegate( 27 | this, 28 | getMainComponentName(), 29 | // If you opted-in for the New Architecture, we enable the Fabric Renderer. 30 | DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled 31 | // If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18). 32 | DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /template/macos/HelloWorld-macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | NSExceptionDomains 30 | 31 | localhost 32 | 33 | NSExceptionAllowsInsecureHTTPLoads 34 | 35 | 36 | 37 | 38 | NSMainStoryboardFile 39 | Main 40 | NSPrincipalClass 41 | NSApplication 42 | NSSupportsAutomaticTermination 43 | 44 | NSSupportsSuddenTermination 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "custom-prebuild-example", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "macos": "react-native run-macos", 9 | "windows": "react-native run-windows", 10 | "start": "react-native start", 11 | "test": "jest", 12 | "lint": "eslint ." 13 | }, 14 | "dependencies": { 15 | "expo": "^48.0.11", 16 | "react": "~18.2.0", 17 | "react-native": "^0.71.7", 18 | "react-native-macos": "^0.71.2", 19 | "react-native-windows": "0.71.6" 20 | }, 21 | "devDependencies": { 22 | "@babel/core": "^7.20.0", 23 | "@babel/runtime": "^7.20.0", 24 | "@react-native-community/eslint-config": "^3.2.0", 25 | "@tsconfig/react-native": "^2.0.2", 26 | "babel-jest": "^29.2.1", 27 | "eslint": "^8.19.0", 28 | "jest": "^29.2.1", 29 | "metro-config": "^0.73.9", 30 | "metro-react-native-babel-preset": "^0.73.9", 31 | "react-test-renderer": "17.0.2", 32 | "typescript": "4.8.4" 33 | }, 34 | "resolutions": { 35 | "@expo/cli": "file:./plugins/expo-cli-670287b.tgz", 36 | "@expo/config-plugins": "file:./plugins/expo-config-plugins-670287b.tgz" 37 | }, 38 | "eslintConfig": { 39 | "extends": "@react-native-community" 40 | }, 41 | "jest": { 42 | "preset": "react-native" 43 | }, 44 | "prettier": { 45 | "arrowParens": "avoid", 46 | "bracketSameLine": true, 47 | "bracketSpacing": false, 48 | "singleQuote": true, 49 | "trailingComma": "all" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "custom-prebuild-template", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "macos": "react-native run-macos", 9 | "windows": "react-native run-windows", 10 | "start": "react-native start", 11 | "test": "jest", 12 | "lint": "eslint ." 13 | }, 14 | "dependencies": { 15 | "expo": "^48.0.11", 16 | "react": "~18.2.0", 17 | "react-native": "^0.71.7", 18 | "react-native-macos": "^0.71.2", 19 | "react-native-windows": "0.71.6" 20 | }, 21 | "devDependencies": { 22 | "@babel/core": "^7.20.0", 23 | "@babel/runtime": "^7.20.0", 24 | "@react-native-community/eslint-config": "^3.2.0", 25 | "@tsconfig/react-native": "^2.0.2", 26 | "babel-jest": "^29.2.1", 27 | "eslint": "^8.19.0", 28 | "jest": "^29.2.1", 29 | "metro-react-native-babel-preset": "^0.73.9", 30 | "react-test-renderer": "17.0.2", 31 | "metro-config": "^0.73.9", 32 | "typescript": "4.8.4" 33 | }, 34 | "resolutions": { 35 | "@expo/cli": "file:./plugins/expo-cli-670287b.tgz", 36 | "@expo/config-plugins": "file:./plugins/expo-config-plugins-670287b.tgz" 37 | }, 38 | "eslintConfig": { 39 | "extends": "@react-native-community" 40 | }, 41 | "jest": { 42 | "preset": "react-native" 43 | }, 44 | "prettier": { 45 | "arrowParens": "avoid", 46 | "bracketSameLine": true, 47 | "bracketSpacing": false, 48 | "singleQuote": true, 49 | "trailingComma": "all" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/plugins/windows/withNuGetSources.js: -------------------------------------------------------------------------------- 1 | const { withWindowsNuGet, addWindowsWarning } = require('./base'); 2 | 3 | /** 4 | * Modify the `windows/NuGet.Config` file to add certain sources. 5 | * Supported options are all sections on the nuget config documentation, using a dictionary. 6 | * 7 | * @example ```{ 8 | * packageSources: { 'NuGet.org': 'https://api.nuget.org/v3/index.json' }, 9 | * disabledPackageSources: {}, 10 | * }``` 11 | * 12 | * @see https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file 13 | * @type {import('expo/config-plugins').ConfigPlugin} 14 | */ 15 | function withNuGetSources(c, options = {}) { 16 | return withWindowsNuGet(c, (config) => { 17 | const configuration = config.modResults.contents.configuration; 18 | 19 | if (!configuration) { 20 | addWindowsWarning('NuGet.Config', 'Malformed NuGet.Config file, please generate from a clean state.'); 21 | return config; 22 | } 23 | 24 | if (options.packageSources) { 25 | const { add } = createBlock(options.packageSources); 26 | configuration.packageSources = [{ clear: '', add }]; 27 | } 28 | 29 | if (options.disabledPackageSources) { 30 | const { add } = createBlock(options.disabledPackageSources); 31 | configuration.disabledPackageSources = [{ clear: '', add }]; 32 | } 33 | 34 | return config; 35 | }); 36 | } 37 | 38 | function createBlock(entries) { 39 | return { 40 | add: Object.entries(entries).map(([name, value]) => ({ 41 | $: { key: name, value }, 42 | })), 43 | }; 44 | } 45 | 46 | module.exports = withNuGetSources; 47 | -------------------------------------------------------------------------------- /template/plugins/windows/withNuGetSources.js: -------------------------------------------------------------------------------- 1 | const { withWindowsNuGet, addWindowsWarning } = require('./base'); 2 | 3 | /** 4 | * Modify the `windows/NuGet.Config` file to add certain sources. 5 | * Supported options are all sections on the nuget config documentation, using a dictionary. 6 | * 7 | * @example ```{ 8 | * packageSources: { 'NuGet.org': 'https://api.nuget.org/v3/index.json' }, 9 | * disabledPackageSources: {}, 10 | * }``` 11 | * 12 | * @see https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file 13 | * @type {import('expo/config-plugins').ConfigPlugin} 14 | */ 15 | function withNuGetSources(c, options = {}) { 16 | return withWindowsNuGet(c, (config) => { 17 | const configuration = config.modResults.contents.configuration; 18 | 19 | if (!configuration) { 20 | addWindowsWarning('NuGet.Config', 'Malformed NuGet.Config file, please generate from a clean state.'); 21 | return config; 22 | } 23 | 24 | if (options.packageSources) { 25 | const { add } = createBlock(options.packageSources); 26 | configuration.packageSources = [{ clear: '', add }]; 27 | } 28 | 29 | if (options.disabledPackageSources) { 30 | const { add } = createBlock(options.disabledPackageSources); 31 | configuration.disabledPackageSources = [{ clear: '', add }]; 32 | } 33 | 34 | return config; 35 | }); 36 | } 37 | 38 | function createBlock(entries) { 39 | return { 40 | add: Object.entries(entries).map(([name, value]) => ({ 41 | $: { key: name, value }, 42 | })), 43 | }; 44 | } 45 | 46 | module.exports = withNuGetSources; 47 | -------------------------------------------------------------------------------- /template/windows/helloworld/Package.appxmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | helloworld 18 | cedri 19 | Assets\StoreLogo.png 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /template/ios/HelloWorld/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Hello App Display Name 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(CURRENT_PROJECT_VERSION) 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSExceptionDomains 30 | 31 | localhost 32 | 33 | NSExceptionAllowsInsecureHTTPLoads 34 | 35 | 36 | 37 | 38 | NSLocationWhenInUseUsageDescription 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UIViewControllerBasedStatusBarAppearance 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /template/macos/HelloWorld-iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | $(PRODUCT_NAME) 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSExceptionDomains 32 | 33 | localhost 34 | 35 | NSExceptionAllowsInsecureHTTPLoads 36 | 37 | 38 | 39 | 40 | NSLocationWhenInUseUsageDescription 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIRequiredDeviceCapabilities 45 | 46 | armv7 47 | 48 | UISupportedInterfaceOrientations 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationLandscapeLeft 52 | UIInterfaceOrientationLandscapeRight 53 | 54 | UIViewControllerBasedStatusBarAppearance 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /app/plugins/windows/withExperimentalFeatures.js: -------------------------------------------------------------------------------- 1 | const { withWindowsExperimentalFeatures } = require('./base'); 2 | 3 | const propertyGroupLabel = 'Microsoft.ReactNative Experimental Features'; 4 | 5 | /** 6 | * Modify the `windows/ExperimentalFeatures.props` file to enable/disable features. 7 | * Supported features are: 8 | * - `useHermes` -> Enables default usage of Hermes. 9 | * - `useWinUI3` -> Changes compilation to assume use of WinUI 3 instead of System XAML. 10 | * - `useNuget` -> Changes compilation to assume use of Microsoft.ReactNative NuGet packages instead of building the framework from source. 11 | * - `useReactFeatureSet` -> ??? (no docs found) 12 | * 13 | * @type {import('expo/config-plugins').ConfigPlugin} 14 | */ 15 | function withExperimentalFeatures(c, options = {}) { 16 | return withWindowsExperimentalFeatures(c, (config) => { 17 | // Find the experimental features block 18 | const features = config.modResults.contents.Project.PropertyGroup.find( 19 | property => property.$?.Label === propertyGroupLabel 20 | ); 21 | 22 | // If it doesn't exists, make sure to warn the user 23 | if (!features) { 24 | throw new Error(`File is missing , replace the malformed file from the template.`); 25 | } 26 | 27 | // Compare all the options with the features settings, and update where necessary 28 | 29 | if (options.useHermes !== undefined) { 30 | features.UseHermes = [options.useHermes]; 31 | } 32 | 33 | if (options.useWinUI3 !== undefined) { 34 | features.UseWinUI3 = [options.useWinUI3]; 35 | } 36 | 37 | if (options.useNuget !== undefined) { 38 | features.UseExperimentalNuget = [options.useNuget]; 39 | } 40 | 41 | if (options.useReactFeatureSet !== undefined) { 42 | features.ReactExperimentalFeaturesSet = [options.useReactFeatureSet]; 43 | } 44 | 45 | return config; 46 | }); 47 | }; 48 | 49 | module.exports = withExperimentalFeatures; 50 | -------------------------------------------------------------------------------- /template/plugins/windows/withExperimentalFeatures.js: -------------------------------------------------------------------------------- 1 | const { withWindowsExperimentalFeatures } = require('./base'); 2 | 3 | const propertyGroupLabel = 'Microsoft.ReactNative Experimental Features'; 4 | 5 | /** 6 | * Modify the `windows/ExperimentalFeatures.props` file to enable/disable features. 7 | * Supported features are: 8 | * - `useHermes` -> Enables default usage of Hermes. 9 | * - `useWinUI3` -> Changes compilation to assume use of WinUI 3 instead of System XAML. 10 | * - `useNuget` -> Changes compilation to assume use of Microsoft.ReactNative NuGet packages instead of building the framework from source. 11 | * - `useReactFeatureSet` -> ??? (no docs found) 12 | * 13 | * @type {import('expo/config-plugins').ConfigPlugin} 14 | */ 15 | function withExperimentalFeatures(c, options = {}) { 16 | return withWindowsExperimentalFeatures(c, (config) => { 17 | // Find the experimental features block 18 | const features = config.modResults.contents.Project.PropertyGroup.find( 19 | property => property.$?.Label === propertyGroupLabel 20 | ); 21 | 22 | // If it doesn't exists, make sure to warn the user 23 | if (!features) { 24 | throw new Error(`File is missing , replace the malformed file from the template.`); 25 | } 26 | 27 | // Compare all the options with the features settings, and update where necessary 28 | 29 | if (options.useHermes !== undefined) { 30 | features.UseHermes = [options.useHermes]; 31 | } 32 | 33 | if (options.useWinUI3 !== undefined) { 34 | features.UseWinUI3 = [options.useWinUI3]; 35 | } 36 | 37 | if (options.useNuget !== undefined) { 38 | features.UseExperimentalNuget = [options.useNuget]; 39 | } 40 | 41 | if (options.useReactFeatureSet !== undefined) { 42 | features.ReactExperimentalFeaturesSet = [options.useReactFeatureSet]; 43 | } 44 | 45 | return config; 46 | }); 47 | }; 48 | 49 | module.exports = withExperimentalFeatures; 50 | -------------------------------------------------------------------------------- /app/plugins/_utils/platforms.js: -------------------------------------------------------------------------------- 1 | const { WarningAggregator, withMod } = require('@expo/config-plugins'); 2 | const { provider, withGeneratedBaseMods } = require('@expo/config-plugins/build/plugins/createBaseMod'); 3 | 4 | /** 5 | * @typedef {import('@expo/config-plugins').ExportedConfig} ExportedConfig 6 | * @typedef {import('@expo/config-plugins').ConfigPlugin>} UnknownConfigPlugin 7 | * @typedef {import('@expo/config-plugins/build/plugins/createBaseMod').provider} ModProvider 8 | */ 9 | 10 | /** 11 | * Create a platform specific warning aggregator. 12 | * 13 | * @param {string} platform 14 | */ 15 | function createPlatformWarning(platform) { 16 | return WarningAggregator.addWarningForPlatform.bind(this, platform); 17 | } 18 | 19 | /** 20 | * Create a base modifier that contains all information about the platform. 21 | * This returns a config plugin that must be added as LAST plugin. 22 | * 23 | * @param {string} platform - Name of the platform to support 24 | * @param {Object} providers - Platform-specific (file) providers for mod access 25 | */ 26 | function createPlatformBaseMod(platform, providers) { 27 | /** @type {Object} */ 28 | const platformProviders = { 29 | dangerous: provider({ 30 | getFilePath() { 31 | return ''; 32 | }, 33 | async read() { 34 | return {}; 35 | }, 36 | async write() {}, 37 | }), 38 | ...providers, 39 | }; 40 | 41 | /** 42 | * @param {ExportedConfig} config 43 | * @param {ModOptions & (typeof defaultProviders)} [props] 44 | * @return {ExportedConfig} 45 | */ 46 | return function withBaseMods(config, { providers, ...props } = {}) { 47 | return withGeneratedBaseMods(config, { 48 | ...props, 49 | platform, 50 | providers: platformProviders, 51 | }); 52 | } 53 | } 54 | 55 | module.exports = { 56 | createPlatformBaseMod, 57 | createPlatformWarning, 58 | modProvider: provider, 59 | withPlatformMod: withMod, 60 | }; 61 | -------------------------------------------------------------------------------- /template/plugins/_utils/platforms.js: -------------------------------------------------------------------------------- 1 | const { WarningAggregator, withMod } = require('@expo/config-plugins'); 2 | const { provider, withGeneratedBaseMods } = require('@expo/config-plugins/build/plugins/createBaseMod'); 3 | 4 | /** 5 | * @typedef {import('@expo/config-plugins').ExportedConfig} ExportedConfig 6 | * @typedef {import('@expo/config-plugins').ConfigPlugin>} UnknownConfigPlugin 7 | * @typedef {import('@expo/config-plugins/build/plugins/createBaseMod').provider} ModProvider 8 | */ 9 | 10 | /** 11 | * Create a platform specific warning aggregator. 12 | * 13 | * @param {string} platform 14 | */ 15 | function createPlatformWarning(platform) { 16 | return WarningAggregator.addWarningForPlatform.bind(this, platform); 17 | } 18 | 19 | /** 20 | * Create a base modifier that contains all information about the platform. 21 | * This returns a config plugin that must be added as LAST plugin. 22 | * 23 | * @param {string} platform - Name of the platform to support 24 | * @param {Object} providers - Platform-specific (file) providers for mod access 25 | */ 26 | function createPlatformBaseMod(platform, providers) { 27 | /** @type {Object} */ 28 | const platformProviders = { 29 | dangerous: provider({ 30 | getFilePath() { 31 | return ''; 32 | }, 33 | async read() { 34 | return {}; 35 | }, 36 | async write() {}, 37 | }), 38 | ...providers, 39 | }; 40 | 41 | /** 42 | * @param {ExportedConfig} config 43 | * @param {ModOptions & (typeof defaultProviders)} [props] 44 | * @return {ExportedConfig} 45 | */ 46 | return function withBaseMods(config, { providers, ...props } = {}) { 47 | return withGeneratedBaseMods(config, { 48 | ...props, 49 | platform, 50 | providers: platformProviders, 51 | }); 52 | } 53 | } 54 | 55 | module.exports = { 56 | createPlatformBaseMod, 57 | createPlatformWarning, 58 | modProvider: provider, 59 | withPlatformMod: withMod, 60 | }; 61 | -------------------------------------------------------------------------------- /template/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Version of flipper SDK to use with React Native 28 | FLIPPER_VERSION=0.125.0 29 | 30 | # Use this property to specify which architecture you want to build. 31 | # You can also override it from the CLI using 32 | # ./gradlew -PreactNativeArchitectures=x86_64 33 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 34 | 35 | # Use this property to enable support to the new architecture. 36 | # This will allow you to use TurboModules and the Fabric render in 37 | # your application. You should enable this flag either if you want 38 | # to write custom TurboModules/Fabric components OR use libraries that 39 | # are providing them. 40 | newArchEnabled=false 41 | 42 | # Use this property to enable or disable the Hermes JS engine. 43 | # If set to false, you will be using JSC instead. 44 | expo.jsEngine=jsc 45 | -------------------------------------------------------------------------------- /template/android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 21 | 22 | 23 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /template/windows/helloworld/helloworld.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Assets 25 | 26 | 27 | Assets 28 | 29 | 30 | Assets 31 | 32 | 33 | Assets 34 | 35 | 36 | Assets 37 | 38 | 39 | Assets 40 | 41 | 42 | Assets 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {e48dc53e-40b1-40cb-970a-f89935452892} 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /template/android/app/src/main/java/com/helloworld/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.helloworld; 2 | 3 | import android.app.Application; 4 | import com.facebook.react.PackageList; 5 | import com.facebook.react.ReactApplication; 6 | import com.facebook.react.ReactNativeHost; 7 | import com.facebook.react.ReactPackage; 8 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; 9 | import com.facebook.react.defaults.DefaultReactNativeHost; 10 | import com.facebook.soloader.SoLoader; 11 | import java.util.List; 12 | 13 | public class MainApplication extends Application implements ReactApplication { 14 | 15 | private final ReactNativeHost mReactNativeHost = 16 | new DefaultReactNativeHost(this) { 17 | @Override 18 | public boolean getUseDeveloperSupport() { 19 | return BuildConfig.DEBUG; 20 | } 21 | 22 | @Override 23 | protected List getPackages() { 24 | @SuppressWarnings("UnnecessaryLocalVariable") 25 | List packages = new PackageList(this).getPackages(); 26 | // Packages that cannot be autolinked yet can be added manually here, for example: 27 | // packages.add(new MyReactNativePackage()); 28 | return packages; 29 | } 30 | 31 | @Override 32 | protected String getJSMainModuleName() { 33 | return "index"; 34 | } 35 | 36 | @Override 37 | protected boolean isNewArchEnabled() { 38 | return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; 39 | } 40 | 41 | @Override 42 | protected Boolean isHermesEnabled() { 43 | return BuildConfig.IS_HERMES_ENABLED; 44 | } 45 | }; 46 | 47 | @Override 48 | public ReactNativeHost getReactNativeHost() { 49 | return mReactNativeHost; 50 | } 51 | 52 | @Override 53 | public void onCreate() { 54 | super.onCreate(); 55 | SoLoader.init(this, /* native exopackage */ false); 56 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 57 | // If you opted-in for the New Architecture, we load the native entry point for this app. 58 | DefaultNewArchitectureEntryPoint.load(); 59 | } 60 | ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /template/ios/HelloWorldTests/HelloWorldTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface HelloWorldTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation HelloWorldTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction( 38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 39 | if (level >= RCTLogLevelError) { 40 | redboxError = message; 41 | } 42 | }); 43 | #endif 44 | 45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 48 | 49 | foundElement = [self findSubviewInView:vc.view 50 | matching:^BOOL(UIView *view) { 51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 52 | return YES; 53 | } 54 | return NO; 55 | }]; 56 | } 57 | 58 | #ifdef DEBUG 59 | RCTSetLogFunction(RCTDefaultLogFunction); 60 | #endif 61 | 62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /app/plugins/universal/withJsEngine.js: -------------------------------------------------------------------------------- 1 | const { withGradleProperties, withPodfileProperties } = require('expo/config-plugins'); 2 | 3 | /** 4 | * Switch JS engines on all supported platforms, including all out-of-tree platforms. 5 | * Supported property is: 6 | * - `engine` - `hermes` or `jsc` 7 | * 8 | * @type {import('expo/config-plugins').ConfigPlugin} 9 | */ 10 | function withJsEngine(config, options = { engine: 'jsc' }) { 11 | config = withHermesAndroid(config, options); 12 | config = withHermesIOS(config, options); 13 | config = withHermesMacOS(config, options); 14 | config = withHermesWindows(config, options); 15 | return config; 16 | } 17 | 18 | function withHermesAndroid(config, { engine } = { engine: 'jsc' }) { 19 | return withGradleProperties(config, config => { 20 | const existing = config.modResults.find( 21 | (item) => item.type === 'property' && item.key === 'expo.jsEngine' 22 | ); 23 | 24 | if (existing) { 25 | existing.value = engine; 26 | } else { 27 | config.modResults.push({ 28 | type: 'property', 29 | key: 'expo.jsEngine', 30 | value: engine, 31 | }); 32 | } 33 | 34 | return config; 35 | }); 36 | } 37 | 38 | function withHermesIOS(config, { engine } = { engine: 'jsc' }) { 39 | return withPodfileProperties(config, config => { 40 | config.modResults['expo.jsEngine'] = engine; 41 | return config; 42 | }); 43 | } 44 | 45 | /** Lazy-plugin, only runs when the macos podfile properties plugin was found. */ 46 | function withHermesMacOS(config, { engine } = { engine: 'jsc' }) { 47 | try { 48 | const { withMacOSPodfileProperties } = require('../macos/base'); 49 | return withMacOSPodfileProperties(config, config => { 50 | config.modResults.contents['expo.jsEngine'] = engine; 51 | return config; 52 | }); 53 | } catch { 54 | return config; // Skip this plugin 55 | } 56 | } 57 | 58 | /** 59 | * Lazy-plugin, only runs when the macos podfile properties plugin was found. 60 | * Note, Windows uses Chakra instead of JSC 61 | */ 62 | function withHermesWindows(config, { engine } = { engine: 'jsc' }) { 63 | try { 64 | const withWindowsExperimentalFeatures = require('../windows/withExperimentalFeatures'); 65 | return withWindowsExperimentalFeatures(config, { useHermes: engine === 'hermes' }); 66 | } catch { 67 | return config; // Skip this plugin 68 | } 69 | } 70 | 71 | module.exports = withJsEngine; 72 | -------------------------------------------------------------------------------- /template/plugins/universal/withJsEngine.js: -------------------------------------------------------------------------------- 1 | const { withGradleProperties, withPodfileProperties } = require('expo/config-plugins'); 2 | 3 | /** 4 | * Switch JS engines on all supported platforms, including all out-of-tree platforms. 5 | * Supported property is: 6 | * - `engine` - `hermes` or `jsc` 7 | * 8 | * @type {import('expo/config-plugins').ConfigPlugin} 9 | */ 10 | function withJsEngine(config, options = { engine: 'jsc' }) { 11 | config = withHermesAndroid(config, options); 12 | config = withHermesIOS(config, options); 13 | config = withHermesMacOS(config, options); 14 | config = withHermesWindows(config, options); 15 | return config; 16 | } 17 | 18 | function withHermesAndroid(config, { engine } = { engine: 'jsc' }) { 19 | return withGradleProperties(config, config => { 20 | const existing = config.modResults.find( 21 | (item) => item.type === 'property' && item.key === 'expo.jsEngine' 22 | ); 23 | 24 | if (existing) { 25 | existing.value = engine; 26 | } else { 27 | config.modResults.push({ 28 | type: 'property', 29 | key: 'expo.jsEngine', 30 | value: engine, 31 | }); 32 | } 33 | 34 | return config; 35 | }); 36 | } 37 | 38 | function withHermesIOS(config, { engine } = { engine: 'jsc' }) { 39 | return withPodfileProperties(config, config => { 40 | config.modResults['expo.jsEngine'] = engine; 41 | return config; 42 | }); 43 | } 44 | 45 | /** Lazy-plugin, only runs when the macos podfile properties plugin was found. */ 46 | function withHermesMacOS(config, { engine } = { engine: 'jsc' }) { 47 | try { 48 | const { withMacOSPodfileProperties } = require('../macos/base'); 49 | return withMacOSPodfileProperties(config, config => { 50 | config.modResults.contents['expo.jsEngine'] = engine; 51 | return config; 52 | }); 53 | } catch { 54 | return config; // Skip this plugin 55 | } 56 | } 57 | 58 | /** 59 | * Lazy-plugin, only runs when the macos podfile properties plugin was found. 60 | * Note, Windows uses Chakra instead of JSC 61 | */ 62 | function withHermesWindows(config, { engine } = { engine: 'jsc' }) { 63 | try { 64 | const withWindowsExperimentalFeatures = require('../windows/withExperimentalFeatures'); 65 | return withWindowsExperimentalFeatures(config, { useHermes: engine === 'hermes' }); 66 | } catch { 67 | return config; // Skip this plugin 68 | } 69 | } 70 | 71 | module.exports = withJsEngine; 72 | -------------------------------------------------------------------------------- /template/ios/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../node_modules/react-native/scripts/react_native_pods' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | require 'json' 5 | podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {} 6 | 7 | 8 | platform :ios, min_ios_version_supported 9 | prepare_react_native_project! 10 | 11 | # If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. 12 | # because `react-native-flipper` depends on (FlipperKit,...) that will be excluded 13 | # 14 | # To fix this you can also exclude `react-native-flipper` using a `react-native.config.js` 15 | # ```js 16 | # module.exports = { 17 | # dependencies: { 18 | # ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), 19 | # ``` 20 | flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled 21 | 22 | linkage = ENV['USE_FRAMEWORKS'] 23 | if linkage != nil 24 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green 25 | use_frameworks! :linkage => linkage.to_sym 26 | end 27 | 28 | target 'HelloWorld' do 29 | config = use_native_modules! 30 | 31 | # Flags change depending on the env values. 32 | flags = get_default_flags() 33 | 34 | use_react_native!( 35 | :path => config[:reactNativePath], 36 | # Hermes is now enabled by default. Disable by setting this flag to false. 37 | # Upcoming versions of React Native may rely on get_default_flags(), but 38 | # we make it explicit here to aid in the React Native upgrade process. 39 | :hermes_enabled => podfile_properties['expo.jsEngine'] == nil || podfile_properties['expo.jsEngine'] == 'hermes', 40 | :fabric_enabled => flags[:fabric_enabled], 41 | # Enables Flipper. 42 | # 43 | # Note that if you have use_frameworks! enabled, Flipper will not work and 44 | # you should disable the next line. 45 | :flipper_configuration => flipper_config, 46 | # An absolute path to your application root. 47 | :app_path => "#{Pod::Config.instance.installation_root}/.." 48 | ) 49 | 50 | target 'HelloWorldTests' do 51 | inherit! :complete 52 | # Pods for testing 53 | end 54 | 55 | post_install do |installer| 56 | react_native_post_install( 57 | installer, 58 | # Set `mac_catalyst_enabled` to `true` in order to apply patches 59 | # necessary for Mac Catalyst builds 60 | :mac_catalyst_enabled => false 61 | ) 62 | __apply_Xcode_12_5_M1_post_install_workaround(installer) 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /app/plugins/macos/base.js: -------------------------------------------------------------------------------- 1 | const { withMod } = require('expo/config-plugins'); 2 | 3 | const { createFileResolver, getFileInfo, writeFile } = require('../_utils/files'); 4 | const { createPlatformWarning, createPlatformBaseMod, modProvider } = require('../_utils/platforms'); 5 | 6 | /** MacOS specific platform warning aggregator */ 7 | const addMacOSWarning = createPlatformWarning('macos'); 8 | /** MacOS specific file resolver */ 9 | const getFilePath = createFileResolver({ addWarning: addMacOSWarning }); 10 | 11 | /** The base config plugin that provides access to all macos-specific files */ 12 | const withMacOSBaseMod = createPlatformBaseMod('macos', { 13 | viewController: modProvider({ 14 | getFilePath({modRequest: {projectRoot}}) { 15 | return getFilePath({ 16 | tag: 'view-controller', 17 | fileName: 'ViewController.m', 18 | globPattern: 'macos/**/ViewController.m', 19 | projectRoot, 20 | }); 21 | }, 22 | async read(filePath) { 23 | return await getFileInfo(filePath, { '.m': 'objc' }); 24 | }, 25 | async write(filePath, {modResults: {contents}}) { 26 | await writeFile(filePath, contents); 27 | }, 28 | }), 29 | podfileProperties: modProvider({ 30 | getFilePath({modRequest: {projectRoot}}) { 31 | return getFilePath({ 32 | tag: 'podfile-properties', 33 | fileName: 'Podfile.properties.json', 34 | globPattern: 'macos/**/Podfile.properties.json', 35 | projectRoot, 36 | }); 37 | }, 38 | async read(filePath) { 39 | const fileInfo = await getFileInfo(filePath, { '.json': 'json' }); 40 | fileInfo.contents = fileInfo.contents ? JSON.parse(fileInfo.contents) : {}; 41 | return fileInfo 42 | }, 43 | async write(filePath, {modResults: {contents}}) { 44 | await writeFile(filePath, JSON.stringify(contents, null, 2)); 45 | }, 46 | 47 | }), 48 | }); 49 | 50 | /** @type {ConfigPlugin} */ 51 | function withMacOSDangerous(config, action) { 52 | return withMod(config, { 53 | platform: 'macos', 54 | mod: 'dangerous', 55 | action, 56 | }); 57 | } 58 | 59 | /** @type {ConfigPlugin} */ 60 | function withMacOSViewController(config, action) { 61 | return withMod(config, { 62 | platform: 'macos', 63 | mod: 'viewController', 64 | action, 65 | }); 66 | } 67 | 68 | /** @type {ConfigPlugin} */ 69 | function withMacOSPodfileProperties(config, action) { 70 | return withMod(config, { 71 | platform: 'macos', 72 | mod: 'podfileProperties', 73 | action, 74 | }); 75 | } 76 | 77 | // Export all macos specific config plugins 78 | module.exports = { 79 | addMacOSWarning, 80 | withMacOSBaseMod, 81 | withMacOSDangerous, 82 | withMacOSViewController, 83 | withMacOSPodfileProperties, 84 | }; 85 | -------------------------------------------------------------------------------- /template/plugins/macos/base.js: -------------------------------------------------------------------------------- 1 | const { withMod } = require('expo/config-plugins'); 2 | 3 | const { createFileResolver, getFileInfo, writeFile } = require('../_utils/files'); 4 | const { createPlatformWarning, createPlatformBaseMod, modProvider } = require('../_utils/platforms'); 5 | 6 | /** MacOS specific platform warning aggregator */ 7 | const addMacOSWarning = createPlatformWarning('macos'); 8 | /** MacOS specific file resolver */ 9 | const getFilePath = createFileResolver({ addWarning: addMacOSWarning }); 10 | 11 | /** The base config plugin that provides access to all macos-specific files */ 12 | const withMacOSBaseMod = createPlatformBaseMod('macos', { 13 | viewController: modProvider({ 14 | getFilePath({modRequest: {projectRoot}}) { 15 | return getFilePath({ 16 | tag: 'view-controller', 17 | fileName: 'ViewController.m', 18 | globPattern: 'macos/**/ViewController.m', 19 | projectRoot, 20 | }); 21 | }, 22 | async read(filePath) { 23 | return await getFileInfo(filePath, { '.m': 'objc' }); 24 | }, 25 | async write(filePath, {modResults: {contents}}) { 26 | await writeFile(filePath, contents); 27 | }, 28 | }), 29 | podfileProperties: modProvider({ 30 | getFilePath({modRequest: {projectRoot}}) { 31 | return getFilePath({ 32 | tag: 'podfile-properties', 33 | fileName: 'Podfile.properties.json', 34 | globPattern: 'macos/**/Podfile.properties.json', 35 | projectRoot, 36 | }); 37 | }, 38 | async read(filePath) { 39 | const fileInfo = await getFileInfo(filePath, { '.json': 'json' }); 40 | fileInfo.contents = fileInfo.contents ? JSON.parse(fileInfo.contents) : {}; 41 | return fileInfo 42 | }, 43 | async write(filePath, {modResults: {contents}}) { 44 | await writeFile(filePath, JSON.stringify(contents, null, 2)); 45 | }, 46 | 47 | }), 48 | }); 49 | 50 | /** @type {ConfigPlugin} */ 51 | function withMacOSDangerous(config, action) { 52 | return withMod(config, { 53 | platform: 'macos', 54 | mod: 'dangerous', 55 | action, 56 | }); 57 | } 58 | 59 | /** @type {ConfigPlugin} */ 60 | function withMacOSViewController(config, action) { 61 | return withMod(config, { 62 | platform: 'macos', 63 | mod: 'viewController', 64 | action, 65 | }); 66 | } 67 | 68 | /** @type {ConfigPlugin} */ 69 | function withMacOSPodfileProperties(config, action) { 70 | return withMod(config, { 71 | platform: 'macos', 72 | mod: 'podfileProperties', 73 | action, 74 | }); 75 | } 76 | 77 | // Export all macos specific config plugins 78 | module.exports = { 79 | addMacOSWarning, 80 | withMacOSBaseMod, 81 | withMacOSDangerous, 82 | withMacOSViewController, 83 | withMacOSPodfileProperties, 84 | }; 85 | -------------------------------------------------------------------------------- /app/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.6) 5 | rexml 6 | activesupport (7.0.4.3) 7 | concurrent-ruby (~> 1.0, >= 1.0.2) 8 | i18n (>= 1.6, < 2) 9 | minitest (>= 5.1) 10 | tzinfo (~> 2.0) 11 | addressable (2.8.4) 12 | public_suffix (>= 2.0.2, < 6.0) 13 | algoliasearch (1.27.5) 14 | httpclient (~> 2.8, >= 2.8.3) 15 | json (>= 1.5.1) 16 | atomos (0.1.3) 17 | claide (1.1.0) 18 | cocoapods (1.12.1) 19 | addressable (~> 2.8) 20 | claide (>= 1.0.2, < 2.0) 21 | cocoapods-core (= 1.12.1) 22 | cocoapods-deintegrate (>= 1.0.3, < 2.0) 23 | cocoapods-downloader (>= 1.6.0, < 2.0) 24 | cocoapods-plugins (>= 1.0.0, < 2.0) 25 | cocoapods-search (>= 1.0.0, < 2.0) 26 | cocoapods-trunk (>= 1.6.0, < 2.0) 27 | cocoapods-try (>= 1.1.0, < 2.0) 28 | colored2 (~> 3.1) 29 | escape (~> 0.0.4) 30 | fourflusher (>= 2.3.0, < 3.0) 31 | gh_inspector (~> 1.0) 32 | molinillo (~> 0.8.0) 33 | nap (~> 1.0) 34 | ruby-macho (>= 2.3.0, < 3.0) 35 | xcodeproj (>= 1.21.0, < 2.0) 36 | cocoapods-core (1.12.1) 37 | activesupport (>= 5.0, < 8) 38 | addressable (~> 2.8) 39 | algoliasearch (~> 1.0) 40 | concurrent-ruby (~> 1.1) 41 | fuzzy_match (~> 2.0.4) 42 | nap (~> 1.0) 43 | netrc (~> 0.11) 44 | public_suffix (~> 4.0) 45 | typhoeus (~> 1.0) 46 | cocoapods-deintegrate (1.0.5) 47 | cocoapods-downloader (1.6.3) 48 | cocoapods-plugins (1.0.0) 49 | nap 50 | cocoapods-search (1.0.1) 51 | cocoapods-trunk (1.6.0) 52 | nap (>= 0.8, < 2.0) 53 | netrc (~> 0.11) 54 | cocoapods-try (1.2.0) 55 | colored2 (3.1.2) 56 | concurrent-ruby (1.2.2) 57 | escape (0.0.4) 58 | ethon (0.16.0) 59 | ffi (>= 1.15.0) 60 | ffi (1.15.5) 61 | fourflusher (2.3.1) 62 | fuzzy_match (2.0.4) 63 | gh_inspector (1.1.3) 64 | httpclient (2.8.3) 65 | i18n (1.12.0) 66 | concurrent-ruby (~> 1.0) 67 | json (2.6.3) 68 | minitest (5.18.0) 69 | molinillo (0.8.0) 70 | nanaimo (0.3.0) 71 | nap (1.1.0) 72 | netrc (0.11.0) 73 | public_suffix (4.0.7) 74 | rexml (3.2.5) 75 | ruby-macho (2.5.1) 76 | typhoeus (1.4.0) 77 | ethon (>= 0.9.0) 78 | tzinfo (2.0.6) 79 | concurrent-ruby (~> 1.0) 80 | xcodeproj (1.22.0) 81 | CFPropertyList (>= 2.3.3, < 4.0) 82 | atomos (~> 0.1.3) 83 | claide (>= 1.0.2, < 2.0) 84 | colored2 (~> 3.1) 85 | nanaimo (~> 0.3.0) 86 | rexml (~> 3.2.4) 87 | 88 | PLATFORMS 89 | ruby 90 | 91 | DEPENDENCIES 92 | cocoapods (~> 1.12) 93 | 94 | RUBY VERSION 95 | ruby 2.7.4p191 96 | 97 | BUNDLED WITH 98 | 2.2.27 99 | -------------------------------------------------------------------------------- /app/plugins/_utils/files.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const { sync: glob } = require('glob'); 4 | 5 | // See: https://github.com/expo/expo/blob/main/packages/@expo/config-plugins/src/ios/Paths.ts#L21-L45 6 | const defaultIgnoredPaths = ['**/@(Carthage|Pods|vendor|node_modules)/**']; 7 | 8 | /** 9 | * Create a file resolver that targets a single file, by glob patter. 10 | * If multiple files are found, a warning is added. 11 | * If none are found, an error is thrown. 12 | * 13 | * @param {{ ignoredPaths: string[], addWarning: (tag: string, message: string) => void}} 14 | */ 15 | function createFileResolver({ ignoredPaths = [], addWarning }) { 16 | return function getFilePath({ projectRoot, globPattern, tag, fileName }) { 17 | const [filePath, ...duplicatePaths] = glob(globPattern, { 18 | absolute: true, 19 | cwd: projectRoot, 20 | ignore: ignoredPaths.concat(defaultIgnoredPaths), 21 | }); 22 | 23 | if (!filePath) { 24 | throw new Error(`Could not locate project file: ${globPattern}`,) 25 | } 26 | 27 | if (duplicatePaths.length) { 28 | warnDuplicateFiles({ 29 | tag, 30 | fileName, 31 | projectRoot, 32 | filePath, 33 | duplicatePaths, 34 | addWarning, 35 | }); 36 | } 37 | 38 | return filePath; 39 | } 40 | } 41 | 42 | function warnDuplicateFiles({ projectRoot, filePath, duplicatePaths, fileName, addWarning }) { 43 | const relativeFilePath = projectRoot ? path.relative(projectRoot, filePath) : filePath; 44 | const relativeDuplicatePaths = projectRoot 45 | ? duplicatePaths.map(v => path.relative(projectRoot, v)) 46 | : duplicatePaths; 47 | addWarning( 48 | `paths-${tag}`, 49 | `Found multiple ${fileName} file paths, using "${relativeFilePath}". Ignored paths: ${JSON.stringify( 50 | relativeDuplicatePaths, 51 | )}`, 52 | ); 53 | } 54 | 55 | /** 56 | * Fetch basic file information for a give file path. 57 | * Note, this also needs a dictionary of file extensions to languages. 58 | * 59 | * @param {string} filePath 60 | * @param {Object} languages 61 | * @returns {Promise<{ path: string, contents: string, language: string }>} 62 | */ 63 | async function getFileInfo(filePath, languages) { 64 | const extension = path.extname(filePath); 65 | const language = languages[extension?.toLowerCase()]; 66 | 67 | if (!language) { 68 | throw new Error(`Unexpected file extension: ${extension}`); 69 | } 70 | 71 | return { 72 | path: path.normalize(filePath), 73 | contents: await fs.promises.readFile(filePath, 'utf8'), 74 | language, 75 | }; 76 | } 77 | 78 | /** 79 | * Modify a file directly, by overwriting it. 80 | * 81 | * @param {string} filePath 82 | * @param {string} contents 83 | * @returns {Promise} 84 | */ 85 | function writeFile(filePath, contents) { 86 | return fs.promises.writeFile(filePath, contents, 'utf8'); 87 | } 88 | 89 | module.exports = { 90 | createFileResolver, 91 | getFileInfo, 92 | writeFile, 93 | }; 94 | -------------------------------------------------------------------------------- /template/plugins/_utils/files.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const { sync: glob } = require('glob'); 4 | 5 | // See: https://github.com/expo/expo/blob/main/packages/@expo/config-plugins/src/ios/Paths.ts#L21-L45 6 | const defaultIgnoredPaths = ['**/@(Carthage|Pods|vendor|node_modules)/**']; 7 | 8 | /** 9 | * Create a file resolver that targets a single file, by glob patter. 10 | * If multiple files are found, a warning is added. 11 | * If none are found, an error is thrown. 12 | * 13 | * @param {{ ignoredPaths: string[], addWarning: (tag: string, message: string) => void}} 14 | */ 15 | function createFileResolver({ ignoredPaths = [], addWarning }) { 16 | return function getFilePath({ projectRoot, globPattern, tag, fileName }) { 17 | const [filePath, ...duplicatePaths] = glob(globPattern, { 18 | absolute: true, 19 | cwd: projectRoot, 20 | ignore: ignoredPaths.concat(defaultIgnoredPaths), 21 | }); 22 | 23 | if (!filePath) { 24 | throw new Error(`Could not locate project file: ${globPattern}`,) 25 | } 26 | 27 | if (duplicatePaths.length) { 28 | warnDuplicateFiles({ 29 | tag, 30 | fileName, 31 | projectRoot, 32 | filePath, 33 | duplicatePaths, 34 | addWarning, 35 | }); 36 | } 37 | 38 | return filePath; 39 | } 40 | } 41 | 42 | function warnDuplicateFiles({ projectRoot, filePath, duplicatePaths, fileName, addWarning }) { 43 | const relativeFilePath = projectRoot ? path.relative(projectRoot, filePath) : filePath; 44 | const relativeDuplicatePaths = projectRoot 45 | ? duplicatePaths.map(v => path.relative(projectRoot, v)) 46 | : duplicatePaths; 47 | addWarning( 48 | `paths-${tag}`, 49 | `Found multiple ${fileName} file paths, using "${relativeFilePath}". Ignored paths: ${JSON.stringify( 50 | relativeDuplicatePaths, 51 | )}`, 52 | ); 53 | } 54 | 55 | /** 56 | * Fetch basic file information for a give file path. 57 | * Note, this also needs a dictionary of file extensions to languages. 58 | * 59 | * @param {string} filePath 60 | * @param {Object} languages 61 | * @returns {Promise<{ path: string, contents: string, language: string }>} 62 | */ 63 | async function getFileInfo(filePath, languages) { 64 | const extension = path.extname(filePath); 65 | const language = languages[extension?.toLowerCase()]; 66 | 67 | if (!language) { 68 | throw new Error(`Unexpected file extension: ${extension}`); 69 | } 70 | 71 | return { 72 | path: path.normalize(filePath), 73 | contents: await fs.promises.readFile(filePath, 'utf8'), 74 | language, 75 | }; 76 | } 77 | 78 | /** 79 | * Modify a file directly, by overwriting it. 80 | * 81 | * @param {string} filePath 82 | * @param {string} contents 83 | * @returns {Promise} 84 | */ 85 | function writeFile(filePath, contents) { 86 | return fs.promises.writeFile(filePath, contents, 'utf8'); 87 | } 88 | 89 | module.exports = { 90 | createFileResolver, 91 | getFileInfo, 92 | writeFile, 93 | }; 94 | -------------------------------------------------------------------------------- /app/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type {PropsWithChildren} from 'react'; 3 | import { 4 | SafeAreaView, 5 | ScrollView, 6 | StatusBar, 7 | StyleSheet, 8 | Text, 9 | useColorScheme, 10 | View, 11 | } from 'react-native'; 12 | 13 | import { 14 | Colors, 15 | DebugInstructions, 16 | Header, 17 | LearnMoreLinks, 18 | ReloadInstructions, 19 | } from 'react-native/Libraries/NewAppScreen'; 20 | 21 | type SectionProps = PropsWithChildren<{ 22 | title: string; 23 | }>; 24 | 25 | function Section({children, title}: SectionProps): JSX.Element { 26 | const isDarkMode = useColorScheme() === 'dark'; 27 | return ( 28 | 29 | 36 | {title} 37 | 38 | 45 | {children} 46 | 47 | 48 | ); 49 | } 50 | 51 | function App(): JSX.Element { 52 | const isDarkMode = useColorScheme() === 'dark'; 53 | 54 | const backgroundStyle = { 55 | backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, 56 | }; 57 | 58 | return ( 59 | 60 | 64 | 67 |

68 | 72 |
73 | Edit App.tsx to change this 74 | screen and then come back to see your edits. 75 |
76 |
77 | 78 |
79 |
80 | 81 |
82 |
83 | Read the docs to discover what to do next: 84 |
85 | 86 |
87 | 88 | 89 | ); 90 | } 91 | 92 | const styles = StyleSheet.create({ 93 | sectionContainer: { 94 | marginTop: 32, 95 | paddingHorizontal: 24, 96 | }, 97 | sectionTitle: { 98 | fontSize: 24, 99 | fontWeight: '600', 100 | }, 101 | sectionDescription: { 102 | marginTop: 8, 103 | fontSize: 18, 104 | fontWeight: '400', 105 | }, 106 | highlight: { 107 | fontWeight: '700', 108 | }, 109 | }); 110 | 111 | export default App; 112 | -------------------------------------------------------------------------------- /template/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type {PropsWithChildren} from 'react'; 3 | import { 4 | SafeAreaView, 5 | ScrollView, 6 | StatusBar, 7 | StyleSheet, 8 | Text, 9 | useColorScheme, 10 | View, 11 | } from 'react-native'; 12 | 13 | import { 14 | Colors, 15 | DebugInstructions, 16 | Header, 17 | LearnMoreLinks, 18 | ReloadInstructions, 19 | } from 'react-native/Libraries/NewAppScreen'; 20 | 21 | type SectionProps = PropsWithChildren<{ 22 | title: string; 23 | }>; 24 | 25 | function Section({children, title}: SectionProps): JSX.Element { 26 | const isDarkMode = useColorScheme() === 'dark'; 27 | return ( 28 | 29 | 36 | {title} 37 | 38 | 45 | {children} 46 | 47 | 48 | ); 49 | } 50 | 51 | function App(): JSX.Element { 52 | const isDarkMode = useColorScheme() === 'dark'; 53 | 54 | const backgroundStyle = { 55 | backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, 56 | }; 57 | 58 | return ( 59 | 60 | 64 | 67 |
68 | 72 |
73 | Edit App.tsx to change this 74 | screen and then come back to see your edits. 75 |
76 |
77 | 78 |
79 |
80 | 81 |
82 |
83 | Read the docs to discover what to do next: 84 |
85 | 86 |
87 | 88 | 89 | ); 90 | } 91 | 92 | const styles = StyleSheet.create({ 93 | sectionContainer: { 94 | marginTop: 32, 95 | paddingHorizontal: 24, 96 | }, 97 | sectionTitle: { 98 | fontSize: 24, 99 | fontWeight: '600', 100 | }, 101 | sectionDescription: { 102 | marginTop: 8, 103 | fontSize: 18, 104 | fontWeight: '400', 105 | }, 106 | highlight: { 107 | fontWeight: '700', 108 | }, 109 | }); 110 | 111 | export default App; 112 | -------------------------------------------------------------------------------- /template/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /template/macos/HelloWorld.xcodeproj/xcshareddata/xcschemes/HelloWorld-iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /template/macos/HelloWorld.xcodeproj/xcshareddata/xcschemes/HelloWorld-macOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /app/plugins/windows/base.js: -------------------------------------------------------------------------------- 1 | const { withMod } = require('expo/config-plugins'); 2 | 3 | const { createFileResolver, getFileInfo, writeFile } = require('../_utils/files'); 4 | const { createPlatformWarning, createPlatformBaseMod, modProvider } = require('../_utils/platforms'); 5 | const { parseXml, stringifyXml } = require('../_utils/serialization'); 6 | 7 | /** @typedef {import('@expo/config-plugins').ConfigPlugin>} ConfigPlugin */ 8 | 9 | /** Windows specific platform warning aggregator */ 10 | const addWindowsWarning = createPlatformWarning('windows'); 11 | /** Windows specific file resolver */ 12 | const getFilePath = createFileResolver({ 13 | ignoredPaths: ['**/(AppPackages|BundleArtifacts)/**'], 14 | addWarning: addWindowsWarning, 15 | }); 16 | 17 | /** The base config plugin that provides access to all windows-specific files */ 18 | const withWindowsBaseMod = createPlatformBaseMod('windows', { 19 | // See: https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file 20 | nuGet: modProvider({ 21 | getFilePath({modRequest: {projectRoot}}) { 22 | return getFilePath({ 23 | tag: 'nuget-config', 24 | fileName: 'NuGet.Config', 25 | globPattern: 'windows/NuGet.Config', 26 | projectRoot, 27 | }); 28 | }, 29 | async read(filePath) { 30 | const fileInfo = await getFileInfo(filePath, { '.config': 'xml' }); 31 | if (fileInfo.contents) { 32 | fileInfo.contents = await parseXml(fileInfo.contents); 33 | } 34 | return fileInfo; 35 | }, 36 | async write(filePath, {modResults: {contents}}) { 37 | await writeFile(filePath, stringifyXml(contents)); 38 | }, 39 | }), 40 | 41 | // See: https://microsoft.github.io/react-native-windows/docs/hermes#using-hermes-in-an-existing-project 42 | experimentalFeatures: modProvider({ 43 | getFilePath({modRequest: {projectRoot}}) { 44 | return getFilePath({ 45 | tag: 'experimental-features', 46 | fileName: 'ExperimentalFeatures.props', 47 | globPattern: 'windows/ExperimentalFeatures.props', 48 | projectRoot, 49 | }); 50 | }, 51 | async read(filePath) { 52 | const fileInfo = await getFileInfo(filePath, { '.props': 'xml' }); 53 | if (fileInfo.contents) { 54 | fileInfo.contents = await parseXml(fileInfo.contents); 55 | } 56 | return fileInfo; 57 | }, 58 | async write(filePath, {modResults: {contents}}) { 59 | await writeFile(filePath, stringifyXml(contents)); 60 | }, 61 | }), 62 | }); 63 | 64 | /** @type {ConfigPlugin} */ 65 | function withWindowsDangerous(config, action) { 66 | return withMod(config, { 67 | platform: 'windows', 68 | mod: 'dangerous', 69 | action, 70 | }); 71 | } 72 | 73 | /** @type {ConfigPlugin} */ 74 | function withWindowsNuGet(config, action) { 75 | return withMod(config, { 76 | platform: 'windows', 77 | mod: 'nuGet', 78 | action, 79 | }); 80 | } 81 | 82 | /** @type {ConfigPlugin} */ 83 | function withWindowsExperimentalFeatures(config, action) { 84 | return withMod(config, { 85 | platform: 'windows', 86 | mod: 'experimentalFeatures', 87 | action, 88 | }); 89 | } 90 | 91 | // Export all windows specific config plugins 92 | module.exports = { 93 | addWindowsWarning, 94 | withWindowsBaseMod, 95 | withWindowsDangerous, 96 | withWindowsNuGet, 97 | withWindowsExperimentalFeatures, 98 | }; 99 | -------------------------------------------------------------------------------- /template/plugins/windows/base.js: -------------------------------------------------------------------------------- 1 | const { withMod } = require('expo/config-plugins'); 2 | 3 | const { createFileResolver, getFileInfo, writeFile } = require('../_utils/files'); 4 | const { createPlatformWarning, createPlatformBaseMod, modProvider } = require('../_utils/platforms'); 5 | const { parseXml, stringifyXml } = require('../_utils/serialization'); 6 | 7 | /** @typedef {import('@expo/config-plugins').ConfigPlugin>} ConfigPlugin */ 8 | 9 | /** Windows specific platform warning aggregator */ 10 | const addWindowsWarning = createPlatformWarning('windows'); 11 | /** Windows specific file resolver */ 12 | const getFilePath = createFileResolver({ 13 | ignoredPaths: ['**/(AppPackages|BundleArtifacts)/**'], 14 | addWarning: addWindowsWarning, 15 | }); 16 | 17 | /** The base config plugin that provides access to all windows-specific files */ 18 | const withWindowsBaseMod = createPlatformBaseMod('windows', { 19 | // See: https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file 20 | nuGet: modProvider({ 21 | getFilePath({modRequest: {projectRoot}}) { 22 | return getFilePath({ 23 | tag: 'nuget-config', 24 | fileName: 'NuGet.Config', 25 | globPattern: 'windows/NuGet.Config', 26 | projectRoot, 27 | }); 28 | }, 29 | async read(filePath) { 30 | const fileInfo = await getFileInfo(filePath, { '.config': 'xml' }); 31 | if (fileInfo.contents) { 32 | fileInfo.contents = await parseXml(fileInfo.contents); 33 | } 34 | return fileInfo; 35 | }, 36 | async write(filePath, {modResults: {contents}}) { 37 | await writeFile(filePath, stringifyXml(contents)); 38 | }, 39 | }), 40 | 41 | // See: https://microsoft.github.io/react-native-windows/docs/hermes#using-hermes-in-an-existing-project 42 | experimentalFeatures: modProvider({ 43 | getFilePath({modRequest: {projectRoot}}) { 44 | return getFilePath({ 45 | tag: 'experimental-features', 46 | fileName: 'ExperimentalFeatures.props', 47 | globPattern: 'windows/ExperimentalFeatures.props', 48 | projectRoot, 49 | }); 50 | }, 51 | async read(filePath) { 52 | const fileInfo = await getFileInfo(filePath, { '.props': 'xml' }); 53 | if (fileInfo.contents) { 54 | fileInfo.contents = await parseXml(fileInfo.contents); 55 | } 56 | return fileInfo; 57 | }, 58 | async write(filePath, {modResults: {contents}}) { 59 | await writeFile(filePath, stringifyXml(contents)); 60 | }, 61 | }), 62 | }); 63 | 64 | /** @type {ConfigPlugin} */ 65 | function withWindowsDangerous(config, action) { 66 | return withMod(config, { 67 | platform: 'windows', 68 | mod: 'dangerous', 69 | action, 70 | }); 71 | } 72 | 73 | /** @type {ConfigPlugin} */ 74 | function withWindowsNuGet(config, action) { 75 | return withMod(config, { 76 | platform: 'windows', 77 | mod: 'nuGet', 78 | action, 79 | }); 80 | } 81 | 82 | /** @type {ConfigPlugin} */ 83 | function withWindowsExperimentalFeatures(config, action) { 84 | return withMod(config, { 85 | platform: 'windows', 86 | mod: 'experimentalFeatures', 87 | action, 88 | }); 89 | } 90 | 91 | // Export all windows specific config plugins 92 | module.exports = { 93 | addWindowsWarning, 94 | withWindowsBaseMod, 95 | withWindowsDangerous, 96 | withWindowsNuGet, 97 | withWindowsExperimentalFeatures, 98 | }; 99 | -------------------------------------------------------------------------------- /template/windows/helloworld/App.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "App.h" 4 | 5 | #include "AutolinkedNativeModules.g.h" 6 | #include "ReactPackageProvider.h" 7 | 8 | using namespace winrt; 9 | using namespace xaml; 10 | using namespace xaml::Controls; 11 | using namespace xaml::Navigation; 12 | 13 | using namespace Windows::ApplicationModel; 14 | namespace winrt::helloworld::implementation 15 | { 16 | /// 17 | /// Initializes the singleton application object. This is the first line of 18 | /// authored code executed, and as such is the logical equivalent of main() or 19 | /// WinMain(). 20 | /// 21 | App::App() noexcept 22 | { 23 | #if BUNDLE 24 | JavaScriptBundleFile(L"index.windows"); 25 | InstanceSettings().UseWebDebugger(false); 26 | InstanceSettings().UseFastRefresh(false); 27 | #else 28 | JavaScriptBundleFile(L"index"); 29 | InstanceSettings().UseWebDebugger(true); 30 | InstanceSettings().UseFastRefresh(true); 31 | #endif 32 | 33 | #if _DEBUG 34 | InstanceSettings().UseDeveloperSupport(true); 35 | #else 36 | InstanceSettings().UseDeveloperSupport(false); 37 | #endif 38 | 39 | RegisterAutolinkedNativeModulePackages(PackageProviders()); // Includes any autolinked modules 40 | 41 | PackageProviders().Append(make()); // Includes all modules in this project 42 | 43 | InitializeComponent(); 44 | } 45 | 46 | /// 47 | /// Invoked when the application is launched normally by the end user. Other entry points 48 | /// will be used such as when the application is launched to open a specific file. 49 | /// 50 | /// Details about the launch request and process. 51 | void App::OnLaunched(activation::LaunchActivatedEventArgs const& e) 52 | { 53 | super::OnLaunched(e); 54 | 55 | Frame rootFrame = Window::Current().Content().as(); 56 | rootFrame.Navigate(xaml_typename(), box_value(e.Arguments())); 57 | } 58 | 59 | /// 60 | /// Invoked when the application is activated by some means other than normal launching. 61 | /// 62 | void App::OnActivated(Activation::IActivatedEventArgs const &e) { 63 | auto preActivationContent = Window::Current().Content(); 64 | super::OnActivated(e); 65 | if (!preActivationContent && Window::Current()) { 66 | Frame rootFrame = Window::Current().Content().as(); 67 | rootFrame.Navigate(xaml_typename(), nullptr); 68 | } 69 | } 70 | 71 | /// 72 | /// Invoked when application execution is being suspended. Application state is saved 73 | /// without knowing whether the application will be terminated or resumed with the contents 74 | /// of memory still intact. 75 | /// 76 | /// The source of the suspend request. 77 | /// Details about the suspend request. 78 | void App::OnSuspending([[maybe_unused]] IInspectable const& sender, [[maybe_unused]] SuspendingEventArgs const& e) 79 | { 80 | // Save application state and stop any background activity 81 | } 82 | 83 | /// 84 | /// Invoked when Navigation to a certain page fails 85 | /// 86 | /// The Frame which failed navigation 87 | /// Details about the navigation failure 88 | void App::OnNavigationFailed(IInspectable const&, NavigationFailedEventArgs const& e) 89 | { 90 | throw hresult_error(E_FAIL, hstring(L"Failed to load Page ") + e.SourcePageType().Name); 91 | } 92 | 93 | } // namespace winrt::helloworld::implementation 94 | -------------------------------------------------------------------------------- /template/ios/HelloWorld.xcodeproj/xcshareddata/xcschemes/HelloWorld.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /template/android/app/src/debug/java/com/helloworld/ReactNativeFlipper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | *

This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | package com.helloworld; 8 | 9 | import android.content.Context; 10 | import com.facebook.flipper.android.AndroidFlipperClient; 11 | import com.facebook.flipper.android.utils.FlipperUtils; 12 | import com.facebook.flipper.core.FlipperClient; 13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; 14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; 15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; 16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping; 17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; 18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; 19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; 20 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; 21 | import com.facebook.react.ReactInstanceEventListener; 22 | import com.facebook.react.ReactInstanceManager; 23 | import com.facebook.react.bridge.ReactContext; 24 | import com.facebook.react.modules.network.NetworkingModule; 25 | import okhttp3.OkHttpClient; 26 | 27 | /** 28 | * Class responsible of loading Flipper inside your React Native application. This is the debug 29 | * flavor of it. Here you can add your own plugins and customize the Flipper setup. 30 | */ 31 | public class ReactNativeFlipper { 32 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 33 | if (FlipperUtils.shouldEnableFlipper(context)) { 34 | final FlipperClient client = AndroidFlipperClient.getInstance(context); 35 | 36 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); 37 | client.addPlugin(new DatabasesFlipperPlugin(context)); 38 | client.addPlugin(new SharedPreferencesFlipperPlugin(context)); 39 | client.addPlugin(CrashReporterPlugin.getInstance()); 40 | 41 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); 42 | NetworkingModule.setCustomClientBuilder( 43 | new NetworkingModule.CustomClientBuilder() { 44 | @Override 45 | public void apply(OkHttpClient.Builder builder) { 46 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); 47 | } 48 | }); 49 | client.addPlugin(networkFlipperPlugin); 50 | client.start(); 51 | 52 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized 53 | // Hence we run if after all native modules have been initialized 54 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); 55 | if (reactContext == null) { 56 | reactInstanceManager.addReactInstanceEventListener( 57 | new ReactInstanceEventListener() { 58 | @Override 59 | public void onReactContextInitialized(ReactContext reactContext) { 60 | reactInstanceManager.removeReactInstanceEventListener(this); 61 | reactContext.runOnNativeModulesQueueThread( 62 | new Runnable() { 63 | @Override 64 | public void run() { 65 | client.addPlugin(new FrescoFlipperPlugin()); 66 | } 67 | }); 68 | } 69 | }); 70 | } else { 71 | client.addPlugin(new FrescoFlipperPlugin()); 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /template/macos/HelloWorld-iOS/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /template/ios/HelloWorld/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |

Customized Prebuild Example

3 |

Demonstration of out-of-tree platforms with prebuild and config plugins

4 |

5 | Structure 6 |  —  7 | Use it 8 |  —  9 | Customize it 10 |

11 |
12 |
13 | 14 | This project demonstrates how Expo Prebuild could be leveraged to run on out-of-tree platforms, with fully customizable templates. 15 | It's set-up to use prebuild for `android`, `ios`, `macos`, and `windows`, using the custom template from this repository. 16 | 17 | > **Warning** 18 | > We recently merged [PR #22224](https://github.com/expo/expo/pull/22224) and [PR #22201](https://github.com/expo/expo/pull/22201), which is required for this demonstration. 19 | > Because these pull requests aren't released yet, this repository contains a modified `@expo/cli` and `@expo/config-plugin` versions. (see [./app/plugins](./app/plugins)) 20 | 21 | ## 📁 Project Structure 22 | 23 | - [`app`](./app) - Example app, created using `npx react-native init` 24 | - [`app/plugins`](./app/plugins) - All plugins required to support out-of-tree platforms 25 | - [`template`](./template) - A customized prebuild template 26 | 27 | ## 🚀 How to use it 28 | 29 | To get your hands dirty, follow these steps. 30 | 31 | - `$ cd ./template` - Before you can use prebuild, we have to create a template tarball 32 | - `$ npm pack` - This creates a tarball that we can pass to prebuild 33 | 34 | After this, you can generate the native files for any of the platforms below. 35 | All of the platform folders (`./android`, `./ios`, `./macos`, and `./windows`) are gitignored and can be fully regenerated. 36 | Use `... prebuild --clean` or `rm -rf ./macos` to regenerate the files. 37 | 38 | ### MacOS 39 | 40 | - `$ cd ./app` - Go to the app folder 41 | - `$ bundle install` - Install all gems 42 | - `$ yarn install` - Install all modules, including prebuild 43 | - `$ npx expo prebuild --platform macos --template ../template/custom-prebuild-template-1.0.0.tgz` - Use prebuild to generate the `./macos` folder 44 | - `$ npx pod-install macos` - Make sure the pods for `./macos` are installed 45 | - `$ npx react-native run-macos` - Run the project normally 46 | 47 | > **Note** 48 | > This not only generates the files from the template, it also runs the [`./app/plugins/macos/withWindowSize`](./app/plugins/macos/withWindowSize.js) plugin. 49 | > Try to customize this in [`./app/app.json`](./app/app.json) and let prebuild configure the native files for you. 50 | 51 | ### Windows 52 | 53 | - `$ cd ./app` - Go to the app folder 54 | - `$ yarn install` - Install all modules, including prebuild 55 | - `$ npx expo prebuild --platform windows --template ../template/custom-prebuild-template-1.0.0.tgz` - Use prebuild to generate the `./windows` folder 56 | - `$ npx react-native run-windows` - Run the project normally 57 | 58 | > **Note** 59 | > This not only generates the files from the template, it also changes settings in `windows/NuGet.Config` and `windows/ExperimentalFeatures.props`. 60 | > Try to customize this in [`./app/app.json`](./app/app.json) and let prebuild configure the native files for you. 61 | 62 | 63 | ### Android 64 | 65 | - `$ cd ./app` - Go to the app folder 66 | - `$ yarn install` - Install all modules, including prebuild 67 | - `$ npx expo prebuild --platform android --template ../template/custom-prebuild-template-1.0.0.tgz` - Use prebuild to generate the `./android` folder 68 | - `$ npx react-native run-android` - Run the project normally 69 | 70 | ### iOS 71 | 72 | - `$ cd ./app` - Go to the app folder 73 | - `$ bundle install` - Install all gems 74 | - `$ yarn install` - Install all modules, including prebuild 75 | - `$ npx expo prebuild --platform ios --template ../template/custom-prebuild-template-1.0.0.tgz` - Use prebuild to generate the `./ios` folder 76 | - `$ npx pod-install ios` - Make sure the pods for `./ios` are installed 77 | - `$ npx react-native run-ios` - Run the project normally 78 | 79 | ## 👷 How to customize it 80 | 81 | Take a look at the existing prebuild plugins, especially the `macos` or `windows` part. 82 | This can be done for any platform, modifier, or change required. 83 | [Learn more about custom base modifiers](https://docs.expo.dev/config-plugins/development-and-debugging/#custom-base-modifiers) 84 | 85 |
86 |
87 | with ❤️  Expo 88 |
89 |
90 | -------------------------------------------------------------------------------- /template/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | apply plugin: "com.facebook.react" 3 | 4 | import com.android.build.OutputFile 5 | 6 | /** 7 | * This is the configuration block to customize your React Native Android app. 8 | * By default you don't need to apply any configuration, just uncomment the lines you need. 9 | */ 10 | react { 11 | /* Folders */ 12 | // The root of your project, i.e. where "package.json" lives. Default is '..' 13 | // root = file("../") 14 | // The folder where the react-native NPM package is. Default is ../node_modules/react-native 15 | // reactNativeDir = file("../node_modules/react-native") 16 | // The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen 17 | // codegenDir = file("../node_modules/react-native-codegen") 18 | // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js 19 | // cliFile = file("../node_modules/react-native/cli.js") 20 | 21 | /* Variants */ 22 | // The list of variants to that are debuggable. For those we're going to 23 | // skip the bundling of the JS bundle and the assets. By default is just 'debug'. 24 | // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. 25 | // debuggableVariants = ["liteDebug", "prodDebug"] 26 | 27 | /* Bundling */ 28 | // A list containing the node command and its flags. Default is just 'node'. 29 | // nodeExecutableAndArgs = ["node"] 30 | // 31 | // The command to run when bundling. By default is 'bundle' 32 | // bundleCommand = "ram-bundle" 33 | // 34 | // The path to the CLI configuration file. Default is empty. 35 | // bundleConfig = file(../rn-cli.config.js) 36 | // 37 | // The name of the generated asset file containing your JS bundle 38 | // bundleAssetName = "MyApplication.android.bundle" 39 | // 40 | // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' 41 | // entryFile = file("../js/MyApplication.android.js") 42 | // 43 | // A list of extra flags to pass to the 'bundle' commands. 44 | // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle 45 | // extraPackagerArgs = [] 46 | 47 | /* Hermes Commands */ 48 | // The hermes compiler command to run. By default it is 'hermesc' 49 | // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" 50 | // 51 | // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" 52 | // hermesFlags = ["-O", "-output-source-map"] 53 | } 54 | 55 | // Override `hermesEnabled` by `expo.jsEngine` 56 | ext { 57 | hermesEnabled = (findProperty('expo.jsEngine') ?: 'hermes') == 'hermes' 58 | } 59 | 60 | /** 61 | * Set this to true to create four separate APKs instead of one, 62 | * one for each native architecture. This is useful if you don't 63 | * use App Bundles (https://developer.android.com/guide/app-bundle/) 64 | * and want to have separate APKs to upload to the Play Store. 65 | */ 66 | def enableSeparateBuildPerCPUArchitecture = false 67 | 68 | /** 69 | * Set this to true to Run Proguard on Release builds to minify the Java bytecode. 70 | */ 71 | def enableProguardInReleaseBuilds = false 72 | 73 | /** 74 | * The preferred build flavor of JavaScriptCore (JSC) 75 | * 76 | * For example, to use the international variant, you can use: 77 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 78 | * 79 | * The international variant includes ICU i18n library and necessary data 80 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 81 | * give correct results when using with locales other than en-US. Note that 82 | * this variant is about 6MiB larger per architecture than default. 83 | */ 84 | def jscFlavor = 'org.webkit:android-jsc:+' 85 | 86 | /** 87 | * Private function to get the list of Native Architectures you want to build. 88 | * This reads the value from reactNativeArchitectures in your gradle.properties 89 | * file and works together with the --active-arch-only flag of react-native run-android. 90 | */ 91 | def reactNativeArchitectures() { 92 | def value = project.getProperties().get("reactNativeArchitectures") 93 | return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] 94 | } 95 | 96 | android { 97 | ndkVersion rootProject.ext.ndkVersion 98 | 99 | compileSdkVersion rootProject.ext.compileSdkVersion 100 | 101 | namespace "com.helloworld" 102 | defaultConfig { 103 | applicationId "com.helloworld" 104 | minSdkVersion rootProject.ext.minSdkVersion 105 | targetSdkVersion rootProject.ext.targetSdkVersion 106 | versionCode 1 107 | versionName "1.0" 108 | } 109 | 110 | splits { 111 | abi { 112 | reset() 113 | enable enableSeparateBuildPerCPUArchitecture 114 | universalApk false // If true, also generate a universal APK 115 | include (*reactNativeArchitectures()) 116 | } 117 | } 118 | signingConfigs { 119 | debug { 120 | storeFile file('debug.keystore') 121 | storePassword 'android' 122 | keyAlias 'androiddebugkey' 123 | keyPassword 'android' 124 | } 125 | } 126 | buildTypes { 127 | debug { 128 | signingConfig signingConfigs.debug 129 | } 130 | release { 131 | // Caution! In production, you need to generate your own keystore file. 132 | // see https://reactnative.dev/docs/signed-apk-android. 133 | signingConfig signingConfigs.debug 134 | minifyEnabled enableProguardInReleaseBuilds 135 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 136 | } 137 | } 138 | 139 | // applicationVariants are e.g. debug, release 140 | applicationVariants.all { variant -> 141 | variant.outputs.each { output -> 142 | // For each separate APK per architecture, set a unique version code as described here: 143 | // https://developer.android.com/studio/build/configure-apk-splits.html 144 | // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc. 145 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] 146 | def abi = output.getFilter(OutputFile.ABI) 147 | if (abi != null) { // null for the universal-debug, universal-release variants 148 | output.versionCodeOverride = 149 | defaultConfig.versionCode * 1000 + versionCodes.get(abi) 150 | } 151 | 152 | } 153 | } 154 | } 155 | 156 | dependencies { 157 | // The version of react-native is set by the React Native Gradle Plugin 158 | implementation("com.facebook.react:react-android") 159 | 160 | implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0") 161 | 162 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") 163 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { 164 | exclude group:'com.squareup.okhttp3', module:'okhttp' 165 | } 166 | 167 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") 168 | if (hermesEnabled.toBoolean()) { 169 | implementation("com.facebook.react:hermes-android") 170 | } else { 171 | implementation jscFlavor 172 | } 173 | } 174 | 175 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) 176 | -------------------------------------------------------------------------------- /template/windows/helloworld/helloworld.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | true 7 | true 8 | true 9 | {136773ed-12cb-4459-a67e-dfc3474cfd99} 10 | helloworld 11 | helloworld 12 | en-US 13 | 17.0 14 | true 15 | Windows Store 16 | 10.0 17 | 18 | 19 | $([MSBuild]::GetDirectoryNameOfFileAbove($(SolutionDir), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\ 20 | 21 | 22 | 23 | 24 | 25 | Debug 26 | ARM64 27 | 28 | 29 | Debug 30 | Win32 31 | 32 | 33 | Debug 34 | x64 35 | 36 | 37 | Release 38 | ARM64 39 | 40 | 41 | Release 42 | Win32 43 | 44 | 45 | Release 46 | x64 47 | 48 | 49 | 50 | Application 51 | Unicode 52 | 53 | 54 | true 55 | true 56 | 57 | 58 | false 59 | true 60 | false 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | Use 77 | pch.h 78 | $(IntDir)pch.pch 79 | Level4 80 | %(AdditionalOptions) /bigobj 81 | 4453;28204 82 | 83 | 84 | 85 | 86 | _DEBUG;%(PreprocessorDefinitions) 87 | 88 | 89 | 90 | 91 | NDEBUG;%(PreprocessorDefinitions) 92 | 93 | 94 | 95 | 96 | MainPage.xaml 97 | Code 98 | 99 | 100 | 101 | 102 | 103 | App.xaml 104 | 105 | 106 | 107 | 108 | Designer 109 | 110 | 111 | 112 | 113 | Designer 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | MainPage.xaml 128 | Code 129 | 130 | 131 | 132 | 133 | Create 134 | 135 | 136 | App.xaml 137 | 138 | 139 | 140 | 141 | 142 | App.xaml 143 | 144 | 145 | MainPage.xaml 146 | Code 147 | 148 | 149 | 150 | 151 | 152 | false 153 | 154 | 155 | 156 | 157 | Designer 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | This project references targets in your node_modules\react-native-windows folder that are missing. The missing file is {0}. 169 | 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /template/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit 84 | 85 | APP_NAME="Gradle" 86 | APP_BASE_NAME=${0##*/} 87 | 88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | 142 | # Increase the maximum file descriptors if we can. 143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 144 | case $MAX_FD in #( 145 | max*) 146 | MAX_FD=$( ulimit -H -n ) || 147 | warn "Could not query maximum file descriptor limit" 148 | esac 149 | case $MAX_FD in #( 150 | '' | soft) :;; #( 151 | *) 152 | ulimit -n "$MAX_FD" || 153 | warn "Could not set maximum file descriptor limit to $MAX_FD" 154 | esac 155 | fi 156 | 157 | # Collect all arguments for the java command, stacking in reverse order: 158 | # * args from the command line 159 | # * the main class name 160 | # * -classpath 161 | # * -D...appname settings 162 | # * --module-path (only if needed) 163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 164 | 165 | # For Cygwin or MSYS, switch paths to Windows format before running java 166 | if "$cygwin" || "$msys" ; then 167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 169 | 170 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 171 | 172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 173 | for arg do 174 | if 175 | case $arg in #( 176 | -*) false ;; # don't mess with options #( 177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 178 | [ -e "$t" ] ;; #( 179 | *) false ;; 180 | esac 181 | then 182 | arg=$( cygpath --path --ignore --mixed "$arg" ) 183 | fi 184 | # Roll the args list around exactly as many times as the number of 185 | # args, so each arg winds up back in the position where it started, but 186 | # possibly modified. 187 | # 188 | # NB: a `for` loop captures its iteration list before it begins, so 189 | # changing the positional parameters here affects neither the number of 190 | # iterations, nor the values presented in `arg`. 191 | shift # remove old arg 192 | set -- "$@" "$arg" # push replacement arg 193 | done 194 | fi 195 | 196 | # Collect all arguments for the java command; 197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 198 | # shell script including quotes and variable substitutions, so put them in 199 | # double quotes to make sure that they get re-expanded; and 200 | # * put everything else in single quotes, so that it's not re-expanded. 201 | 202 | set -- \ 203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 204 | -classpath "$CLASSPATH" \ 205 | org.gradle.wrapper.GradleWrapperMain \ 206 | "$@" 207 | 208 | # Use "xargs" to parse quoted args. 209 | # 210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 211 | # 212 | # In Bash we could simply go: 213 | # 214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 215 | # set -- "${ARGS[@]}" "$@" 216 | # 217 | # but POSIX shell has neither arrays nor command substitution, so instead we 218 | # post-process each arg (as a line of input to sed) to backslash-escape any 219 | # character that might be a shell metacharacter, then use eval to reverse 220 | # that process (while maintaining the separation between arguments), and wrap 221 | # the whole thing up as a single "set" statement. 222 | # 223 | # This will of course break if any of these variables contains a newline or 224 | # an unmatched quote. 225 | # 226 | 227 | eval "set -- $( 228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 229 | xargs -n1 | 230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 231 | tr '\n' ' ' 232 | )" '"$@"' 233 | 234 | exec "$JAVACMD" "$@" 235 | -------------------------------------------------------------------------------- /template/windows/helloworld.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32929.385 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "helloworld", "helloworld\helloworld.vcxproj", "{136773ED-12CB-4459-A67E-DFC3474CFD99}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136} = {F7D32BD0-2749-483E-9A0D-1635EF7E3136} 9 | EndProjectSection 10 | EndProject 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Folly", "..\node_modules\react-native-windows\Folly\Folly.vcxproj", "{A990658C-CE31-4BCC-976F-0FC6B1AF693D}" 12 | EndProject 13 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fmt", "..\node_modules\react-native-windows\fmt\fmt.vcxproj", "{14B93DC8-FD93-4A6D-81CB-8BC96644501C}" 14 | EndProject 15 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactCommon", "..\node_modules\react-native-windows\ReactCommon\ReactCommon.vcxproj", "{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}" 16 | ProjectSection(ProjectDependencies) = postProject 17 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {A990658C-CE31-4BCC-976F-0FC6B1AF693D} 18 | EndProjectSection 19 | EndProject 20 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Chakra", "..\node_modules\react-native-windows\Chakra\Chakra.vcxitems", "{C38970C0-5FBF-4D69-90D8-CBAC225AE895}" 21 | EndProject 22 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative", "..\node_modules\react-native-windows\Microsoft.ReactNative\Microsoft.ReactNative.vcxproj", "{F7D32BD0-2749-483E-9A0D-1635EF7E3136}" 23 | EndProject 24 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Cxx", "..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems", "{DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B}" 25 | EndProject 26 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "..\node_modules\react-native-windows\Common\Common.vcxproj", "{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}" 27 | EndProject 28 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReactNative", "ReactNative", "{5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}" 29 | EndProject 30 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Shared", "..\node_modules\react-native-windows\Shared\Shared.vcxitems", "{2049DBE9-8D13-42C9-AE4B-413AE38FFFD0}" 31 | EndProject 32 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mso", "..\node_modules\react-native-windows\Mso\Mso.vcxitems", "{84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E}" 33 | EndProject 34 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Include", "..\node_modules\react-native-windows\include\Include.vcxitems", "{EF074BA1-2D54-4D49-A28E-5E040B47CD2E}" 35 | EndProject 36 | Global 37 | GlobalSection(SharedMSBuildProjectFiles) = preSolution 38 | ..\node_modules\react-native-windows\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 39 | ..\node_modules\react-native-windows\Mso\Mso.vcxitems*{84e05bfa-cbaf-4f0d-bfb6-4ce85742a57e}*SharedItemsImports = 9 40 | ..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{c38970c0-5fbf-4d69-90d8-cbac225ae895}*SharedItemsImports = 9 41 | ..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{da8b35b3-da00-4b02-bde6-6a397b3fd46b}*SharedItemsImports = 9 42 | ..\node_modules\react-native-windows\include\Include.vcxitems*{ef074ba1-2d54-4d49-a28e-5e040b47cd2e}*SharedItemsImports = 9 43 | ..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 44 | ..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 45 | ..\node_modules\react-native-windows\Mso\Mso.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 46 | ..\node_modules\react-native-windows\Shared\Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 47 | EndGlobalSection 48 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 49 | Debug|x64 = Debug|x64 50 | Debug|x86 = Debug|x86 51 | Debug|ARM64 = Debug|ARM64 52 | Release|x64 = Release|x64 53 | Release|x86 = Release|x86 54 | Release|ARM64 = Release|ARM64 55 | EndGlobalSection 56 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 57 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Debug|ARM64.ActiveCfg = Debug|ARM64 58 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Debug|ARM64.Build.0 = Debug|ARM64 59 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Debug|ARM64.Deploy.0 = Debug|ARM64 60 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Debug|x64.ActiveCfg = Debug|x64 61 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Debug|x64.Build.0 = Debug|x64 62 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Debug|x64.Deploy.0 = Debug|x64 63 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Debug|x86.ActiveCfg = Debug|Win32 64 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Debug|x86.Build.0 = Debug|Win32 65 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Debug|x86.Deploy.0 = Debug|Win32 66 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Release|ARM64.ActiveCfg = Release|ARM64 67 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Release|ARM64.Build.0 = Release|ARM64 68 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Release|ARM64.Deploy.0 = Release|ARM64 69 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Release|x64.ActiveCfg = Release|x64 70 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Release|x64.Build.0 = Release|x64 71 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Release|x64.Deploy.0 = Release|x64 72 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Release|x86.ActiveCfg = Release|Win32 73 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Release|x86.Build.0 = Release|Win32 74 | {136773ED-12CB-4459-A67E-DFC3474CFD99}.Release|x86.Deploy.0 = Release|Win32 75 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM64.ActiveCfg = Debug|ARM64 76 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM64.Build.0 = Debug|ARM64 77 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x64.ActiveCfg = Debug|x64 78 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x64.Build.0 = Debug|x64 79 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x86.ActiveCfg = Debug|Win32 80 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x86.Build.0 = Debug|Win32 81 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM64.ActiveCfg = Release|ARM64 82 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM64.Build.0 = Release|ARM64 83 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x64.ActiveCfg = Release|x64 84 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x64.Build.0 = Release|x64 85 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.ActiveCfg = Release|Win32 86 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.Build.0 = Release|Win32 87 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM64.ActiveCfg = Debug|ARM64 88 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM64.Build.0 = Debug|ARM64 89 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x64.ActiveCfg = Debug|x64 90 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x64.Build.0 = Debug|x64 91 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x86.ActiveCfg = Debug|Win32 92 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x86.Build.0 = Debug|Win32 93 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM64.ActiveCfg = Release|ARM64 94 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM64.Build.0 = Release|ARM64 95 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x64.ActiveCfg = Release|x64 96 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x64.Build.0 = Release|x64 97 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.ActiveCfg = Release|Win32 98 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.Build.0 = Release|Win32 99 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM64.ActiveCfg = Debug|ARM64 100 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM64.Build.0 = Debug|ARM64 101 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x64.ActiveCfg = Debug|x64 102 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x64.Build.0 = Debug|x64 103 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x86.ActiveCfg = Debug|Win32 104 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x86.Build.0 = Debug|Win32 105 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM64.ActiveCfg = Release|ARM64 106 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM64.Build.0 = Release|ARM64 107 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x64.ActiveCfg = Release|x64 108 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x64.Build.0 = Release|x64 109 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.ActiveCfg = Release|Win32 110 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.Build.0 = Release|Win32 111 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM64.ActiveCfg = Debug|ARM64 112 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM64.Build.0 = Debug|ARM64 113 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x64.ActiveCfg = Debug|x64 114 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x64.Build.0 = Debug|x64 115 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x86.ActiveCfg = Debug|Win32 116 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x86.Build.0 = Debug|Win32 117 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM64.ActiveCfg = Release|ARM64 118 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM64.Build.0 = Release|ARM64 119 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x64.ActiveCfg = Release|x64 120 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x64.Build.0 = Release|x64 121 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.ActiveCfg = Release|Win32 122 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.Build.0 = Release|Win32 123 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|ARM64.ActiveCfg = Debug|ARM64 124 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|ARM64.Build.0 = Debug|ARM64 125 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x64.ActiveCfg = Debug|x64 126 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x64.Build.0 = Debug|x64 127 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x86.ActiveCfg = Debug|Win32 128 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x86.Build.0 = Debug|Win32 129 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Debug|x86.Deploy.0 = Debug|Win32 130 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|ARM64.ActiveCfg = Release|ARM64 131 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|ARM64.Build.0 = Release|ARM64 132 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x64.ActiveCfg = Release|x64 133 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x64.Build.0 = Release|x64 134 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x86.ActiveCfg = Release|Win32 135 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x86.Build.0 = Release|Win32 136 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x86.Deploy.0 = Release|Win32 137 | EndGlobalSection 138 | GlobalSection(SolutionProperties) = preSolution 139 | HideSolutionNode = FALSE 140 | EndGlobalSection 141 | GlobalSection(NestedProjects) = preSolution 142 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} 143 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} 144 | {C38970C0-5FBF-4D69-90D8-CBAC225AE895} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} 145 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} 146 | {DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} 147 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} 148 | {2049DBE9-8D13-42C9-AE4B-413AE38FFFD0} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} 149 | {84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} 150 | {EF074BA1-2D54-4D49-A28E-5E040B47CD2E} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} 151 | {14B93DC8-FD93-4A6D-81CB-8BC96644501C} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} 152 | EndGlobalSection 153 | GlobalSection(ExtensibilityGlobals) = postSolution 154 | SolutionGuid = {D43FAD39-F619-437D-BB40-04A3982ACB6A} 155 | EndGlobalSection 156 | EndGlobal 157 | --------------------------------------------------------------------------------