How to Solve JavaScript Module Resolution with File Structure

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the Building React Native Apps for Mac course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to Building React Native Apps for Mac, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course Building React Native Apps for Mac
  • [00:00 - 00:13] So, before we move on with our application, there is one extra thing that we need to take care of. There are two problems with JavaScript itself.

    [00:14 - 00:24] One of them is importing different modules. So you can see here we're importing our containers and our store using relative pads.

    [00:25 - 00:48] So the problem is as your application grows, as your project grows in complexity, whenever you want to move a file or a folder, it gets a lot of work because you have to go into each file and rename all your imports. So we're going to take care of that using a Babel plugin, which is going to make all of our imports absolute.

    [00:49 - 01:09] The second problem is just importing of modules in general because JavaScript is evaluated at runtime. That means sometimes you might get into situations where a module hasn't been completely initialized it, but you're already imported it and you try to call it within another module .

    [01:10 - 01:23] So you get these weird race conditions where things will crash because they just haven't been loaded into memory yet. So we're going to solve most of those problems by using a specific folder structure.

    [01:24 - 01:33] So let's just start resolving the first problem, which are the relative imports . So in order to do this, we need to take care of two aspects.

    [01:34 - 01:43] One is TypeScript itself. We need to give it some hints of how it should solve an absolute import.

    [01:44 - 01:47] And we also need to do it on the JavaScript level. We need to do it on Babel.

    [01:48 - 02:06] Babel is one of the tools that takes care of your JavaScript and compiling it for the device. So if you have used the TypeScript configuration I have given in the course, I have already set a base URL property for you on the TypeScript file.

    [02:07 - 02:22] So this tells TypeScript whenever it sees an import that doesn't have a relative path, it's just going to append this one. It's going to solve everything from the root of our source folder.

    [02:23 - 02:36] So once that's taken care of, now we need to take care of Babel. So in order to do this, we need to install one more dependency into our project , which is Babel plugin module resolver.

    [02:37 - 02:53] So from your terminal, you can just do yarn at the Babel plugin module resolver . That's going to download the dependency and once that's installed, we can go into Babel.config.js.

    [02:54 - 03:04] And I'm just going to take it from the lesson one more time. Below the press its line, you're going to insert the plugins.

    [03:05 - 03:13] So this is just adding the plugin into Babel, very similar to TypeScript. So we're telling the root of our project is the source folder.

    [03:14 - 03:26] So whatever path doesn't have the dot at the beginning, this is going to append it to it. And then we just pass all the extensions that we wanted to resolve for us.

    [03:27 - 03:37] And that's it. So right now I could go into our app.tsx file and just delete this path.

    [03:38 - 03:43] And if I save it, our application should still work. Just fine.

    [03:44 - 03:51] I can right click and reload it. There might be a problem if you're running this for the very first time.

    [03:52 - 04:03] That is that the plugin maybe is loaded into the metro package yet. So if you get some sort of error, what you can do is you just quit the app.

    [04:04 - 04:12] And you also close the metro package. And then we need to clear the caches of metro.

    [04:13 - 04:27] For that we can just use the command that we used before that we created into our package, which is the new command. So this is going to take care of deleting all the caches, all the temporary files from our JavaScript compilation.

    [04:28 - 04:41] And then we can just start it again. So I'm just going to quit this and just run the my quest command one more time.

    [04:42 - 05:22] Just the application get compiled again and everything starts new. So it's working.

    [05:23 - 05:40] We just started the application again and now we can start deleting the relative paths and just use the absolute paths and our application should still work just fine . So that takes care of our first problem, which are the relative imports.

    [05:41 - 05:55] But we still need to do something about the import order to prevent that some modules might not be initialized on time. So in order to do this, we're going to follow one pattern.

    [05:56 - 06:15] So inside of our containers folder, I'm going to create a index.ts file. And inside of this index.ts file, I'm going to export everything from my books container.

    [06:16 - 06:27] Right? So I'm going to create this index file for most of my folders whenever there might be some dependency that I need to worry about.

    [06:28 - 06:59] This allows me, for example, if I, let's just say as my application grows over time and I have more stores, for example, I can change the order how things are loaded, right? So instead of loading the UI store first, I can just move it down and let's say I need to load my API store, for example, right?

    [07:00 - 07:07] Or the API store, firstly, it needs for something else to be initialized. So I don't know.

    [07:08 - 07:20] Let's say a node, a node store, something like that. So this kind of gives me a more explicit way to control how my modules are being loaded.

    [07:21 - 07:30] So right now I only have two index files, one for the stores, one for the containers. So I can go back into my app.ts file.

    [07:31 - 07:46] And instead of importing directly the file, I can import directly from my containers. So this type script and JavaScript are smart enough to know that if you're pointing to a folder, then it should look for the index.ts file.

    [07:47 - 07:51] And it just resolved the import for you. So if we go back into application, everything is still working.

    [07:52 - 07:56] [silence]