DEV Community

Cover image for React Native: How to change the default folder structure
Iacopo Pazzaglia
Iacopo Pazzaglia

Posted on

React Native: How to change the default folder structure

Cover photo taken from Pexels

Hello,

have you ever had the need to change the default React Native folder structure and you spent hours to figure out the correct setup? 🙌

Well, if this is case in this post I'll highlight all the changes needed to move the folders android and ios inside a parent folder called native.
I assume that the project is created with the command react-native init.

From: 

├── ios
├── android

To:

└── native
    ├── ios
    ├── android

Enter fullscreen mode Exit fullscreen mode

Android

Let's start modifying the package.json to specify the new root of the android project:

   "scripts": {
-    "android": "react-native run-android",
+    "android": "react-native run-android --root './native'",
     "ios": "react-native run-ios",

Enter fullscreen mode Exit fullscreen mode

Then we need to create a file called react-native-config.js that is a file used by the react native CLI where we can modify the project configuration.
In this file we set the source directory of the Android project:

module.exports = {
  project: {
    android: {
      sourceDir: './native/android',
    },
  },
}
Enter fullscreen mode Exit fullscreen mode

At this point we configured the CLI to locate the android folder but we still need to update the references of the node_modules folder in each gradle file.

  • settings.gradle
-apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
+apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
Enter fullscreen mode Exit fullscreen mode
  • build.gradle
         mavenLocal()
         maven {
             // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
-            url("$rootDir/../node_modules/react-native/android")
+            url("$rootDir/../../node_modules/react-native/android")
         }
         maven {
             // Android JSC is installed from npm
-            url("$rootDir/../node_modules/jsc-android/dist")
+            url("$rootDir/../../node_modules/jsc-android/dist")
         }

Enter fullscreen mode Exit fullscreen mode
  • app/build.gradle
-apply from: "../../node_modules/react-native/react.gradle"
+apply from: "../../../node_modules/react-native/react.gradle"

 /**
  * Set this to true to create two separate APKs instead of one:

     into 'libs'
 }

-apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
+apply from: file("../../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)


Enter fullscreen mode Exit fullscreen mode

All these changes reflect the moving of the directory one level deeper.

iOS

In iOS as well we need to modify the package.json to specify the new root of the project:

   "scripts": {
-    "ios": "react-native run-ios",
+    "ios": "react-native run-ios --project-path './native/ios'",


Enter fullscreen mode Exit fullscreen mode

Next we need to update the the references of the node_modules folder in the native project.

  • Podfile

Here I put a partial diff of the Podfile to highlight the changes needed.

+    pod 'FBLazyVector', :path => "../../node_modules/react-native/Libraries/FBLazyVector"
-    pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
+    pod 'FBReactNativeSpec', :path => "../../node_modules/react-native/Libraries/FBReactNativeSpec"
-    pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"

Enter fullscreen mode Exit fullscreen mode

after the file is update delete the build folder inside the iOS project if exist and execute pod install.

  • native/ios/<your project name>.xcodeproj/project.pbxproj

Finally we need to update the script under Build Phases->Start Packager in Xcode

Build Phases. Start Packager script

Extra

The last thing to do is to update the .gitignore file to reflect the changes made.

 # Android/IntelliJ
 #
-build/
+native/build/

 # CocoaPods
-/ios/Pods/
+native/ios/Pods/
Enter fullscreen mode Exit fullscreen mode

Conclusion

Now the project is ready to be executed using the usual npm or yarn command 🎉

Let me know in the comments if you know a more straightforward way to achieve the same result!

Top comments (2)

Collapse
 
darylaranha profile image
Daryl Aranha

Really helpful!! thank you...

However, while giving a build I am getting this error.

internal/modules/cjs/loader.js:905
  throw err;

Error: Cannot find module '<project_path>/native/node_modules/react-native/cli.js'
Enter fullscreen mode Exit fullscreen mode

Can you please help me out with this error?

Collapse
 
razonklnbd profile image
Md. Shahadat Hossain Khan • Edited

Nice article, works fine but just one issue.
In the android section 2nd paragraph, something like following text -
"Then we need to create a file called react-native-config.js that is a file"
Here the file name wrong, it should "react-native.config.js" as per current version [0.63.4 & cli-2.0.1] of react-native

Another point, I didn't test it for iOS.

Anyway, great post thanks for share...