I'm in the process of creating a monorepo to hold both my React web app and my React Native app as they share a lot of common code.
The setup i'm trying to get is:
Project
|
+-- web
+-- native
----|------ file.js (should be able to import from 'shared/file2.js')
+-- shared
----|------ file2.js
----|------ package.json (with name="shared")
+-- package.json
From folowing this post: https://blog.callstack.io/a-cure-for-relative-requires-in-react-native-2b263cecf0f6#.4g1o5inru I added a package.json file to the shared folder with:
{ "name": "shared" }
and am starting my native app from the package.json in the root folder like so:
"start-native": "./native/node_modules/react-native/packager/packager.sh"
But for some reason i'm getting the following error:
Any idea what i'm doing wrong or how I can achieve importing files in my RN app from a shared folder that is upstream?
EDIT:
A few details I forgot to mention.
The line giving me the error is (fake file names...):
// in native/file.js
import { aFunctionName } from 'shared/file2'
Also tried adding a name in the package.json (name=proj-root) in the root level and importing like:
import { aFunctionName } from 'proj-root/shared/file2'
Thanks!
Uri
To share code between web and native you should change how you are structuring your folders.
First start with a new project react-native init myProject
this will create the default structure for RN apps.
myProject
|
+-- android
+-- ios
+-- index.android.js
+-- index.ios.js
...
Now create specific folders for web and shared code.
myProject
|
+-- android
+-- ios
+-- index.android.js
+-- index.ios.js
+-- web
+-- shared
----|------ index.js
...
shared/index.js
function hi() {
return 'hi';
}
module.exports = {
hi: hi
};
index.ios.js
import { hi } from './shared/';
I ended up changing the folder structure as stated in @diegopartes answer.
In addition, I wanted to achieve the effect of being able to import from the shared folder using absolute paths from both my web and mobile directories.
For this I did the following:
Web
I moved my webpack.config.js
to the root folder of the app. Inside webpack.config.js I have the following configuration the allows me to import files using absolute paths:
const path = require('path');
const sharedPath = path.join(__dirname, 'shared');
const config = {
...
resolve: {
root: [sharedPath],
},
...
}
now my shared folder acts as a root folder. Meaning, if I have
- shared
-- reducers
-- actions
--- todos.js
I can do an import { addTodo } from 'actions/todos'
Mobile
Here I went by this post which basically says:
Whichever folder you want to be able to import as root from, add a package.json
file with { "name": "FOLDER_NAME" }
. So for to achieve the same import as in the web app:
- shared
-- reducers
-- actions
--- todos.js
--- package.json
Where the package.json
contents is:
{
"name": "actions"
}
Now I can do the same import as I did in the web app from my mobile app files.
EDIT
Regarding node_modules
, I use the same package.json
for both web and mobile. In my webpack.config
I have an array of all React Native packages an these are excluded from my vendor bundle file.
Did you consider to hoist node_modules?
Moreover you can use lerna to achieve what you want instead of self-written solution.