Change project file structure and stop using relative paths

Learning expo using the TabNavigation app.
I’d like to change two things with respect to the default way the files are setup.

  1. I’d like to move all source code pertaining to the app under a directory called src. What do I need to change for this?

  2. I want to specify a common root/root paths for all my imports so that i am no longer doing relative path imports. e.g. Assume that blahStore.js is located at <root>/src/stores/blahStore.js.
    Instead of doing
    import blahStore from '../stores/blahStore' from a file in another directory
    I want to instead be doing
    import blahStore from 'stores/blahStore'
    I’ve seen this previous answer but it doesn’t seem very definitive. Relative paths with Expo
    This also means the babel needs to look in the src directory and then the node_modules directory when searching for a module to import.

Thanks for using expo :slight_smile:

Babel module-resolver is probably the best way to accomplish this. Maybe the official documentation can help you find an efficient way of doing it: GitHub - tleunen/babel-plugin-module-resolver: Custom module resolver plugin for Babel

@davepack thanks for the response.
If I move App.js into the src subfolder, What needs to change so that babel/expo know where to find it?
Not able to determine where this is defined.
If that can’t be moved, thats not an issue. Just wondering.

some comments after investigation

1. Moving App .js

So you can’t really move App.js because it is referenced by a relative path in expo/AppEntry.js. I tried creating an alias in the module_resolver, but that doesn’t work.

2. Using module_resolver to set new roots

using the module resolver plugin seemed straighforward at first, but looks like lots of opportunity to break.
I modified my .babelrc to look like. (the only stuff i added is under the plugin section)

{
	"presets": ["babel-preset-expo"],
	"env": {
		"development": {
		  "plugins": ["transform-react-jsx-source"]
		}
	},
	"plugins": [
		["module-resolver",
		 {
			"root": ["./src", "./node_modules"]
		 }
		]
	]
}

and then I moved all the relevant source (except for App.js) in side the ./src folder.

This seemed to have the desired effect, until it got to a point in the TabNavigation App where it tries to use the AppLoading component. This in turn attempts to use the react-native ActivityIndicator component.
It attempts to add react by calling

const React = require('React');

where the intent is to search it’s own local modules. Guess i need a way to specify “search the current local directory first” in the “root” directive for module_resolver.
In webpack I was able to accomplish the same by instructing it to exclude the node_modules folder. Can’t see how to do that with babel module_resolver plugin.

This leads to an error that looks like
image


I guess the bottom line right now is that it doesn’t look realistic to move the source into a subfolder nor stop using relative paths.

Actually it looks like your issue is capitalization. Code should be const React = require('react');. Notice the lower case ‘r’ in the require. That should resolve at least that problem.

1 Like

Yes, I’m aware of that. That code is actually from react-native. Check out the source for the ActivityIndicator component.

As I interpret it, it is looking for the local “React” folder, instead of the one in my node_modules.

https://github.com/facebook/react-native/blob/master/Libraries/Components/ActivityIndicator/ActivityIndicator.js#L17

I see. I apologize for not reading your whole post before responding. But you’re officially beyond my depth and it seems like this is not an expo specific issue but is perhaps more related to the babel plugin. Have you tried asking your questions there?

I haven’t yet. I thought to try here first because it seems Expo is very opinionated about the project layout and use of relative paths. Also because the build config is completely hidden (where i have previously set this config in other projects).

Guess I’ll try asking questions over there.

Thanks for taking the time to think on this.

  1. Move everything to /src

Create an /src folder within your expo project folder. Then in the App.js you load your Main.js file from the /src folder

/App.js

import React from 'react';
import Main from './src/Main';

const App = () => (
  <Main />
);

export default App;

In the /src/Main.js you can call all your other React Native components from this folder with

import MyStore from './stores/MyStore';

While the structure is /src/stores/MyStore

  1. Relative paths (via Module-Resolver)

If you have a lot of subfolders (all within the /src) and don’t want to go up 3 levels of folders like this:

import MyComponentList from '../../Lists/MyComponentList';

You can use an alias to define a path like this:

  • Open up your .babelrc file
  • Add and edit the following at the end :
"plugins": [
    ["module-resolver", {
      "alias": {
        "your-alias": "./src",
      }
    }]
  ]
  • After you added this and restarted your project you can use the alias everywhere like this:
import MyComponentList from 'your-alias/Lists/MyComponentList';
4 Likes

thx for replying @deveagle
I implemented 1. already in the last couple projects i did. this works well.

for 2. I thought about a custsom “your-alias” for module-resolver but wanted to avoid it if possible. I guess for the moment, this is the only way to do it.

1 Like