DEV Community

Cover image for Understanding Module Specifier
Nick Baughan
Nick Baughan

Posted on • Edited on

Understanding Module Specifier

In my previous post, to keep things simple all code files are living together in the same directory. When importing, specifying "./" and then the name of the file tells the compiler or bundler to look in the current directory to find the file. This simple setup works fine for a simple demonstrative example, but in a real project with even a little bit of complexity we need to organize our files better.

The specifier part of an import statement is how you indicate where the file is located. As I already mentioned, using "./" indicates "look in the current directory". But the files you need in many cases are probably within a subdirectory. In the example below all of the math functionality has been cleaned up and moved into its own folder.

import from a subdirectory

Now, from the index.js file, to access the add.js file, you would need to use the module specifier "./calculator/add.js". This is saying "look in the current directory for a folder named 'calculator', then inside of it, grab the file named 'add.js'"

A feature of the module specifiers spec is that if a file isn't explicitly declared in the import statement, the compiler will look for a file named "index.js". This can be used to organize functionality and to clean up the amount of import statements for the consuming code. As you can see below, all of the operation and constants are imported to an index file, where they can be imported with only one import statement.

Using an Index file

The calculator could be refactored and organized itself. With constants and operations moved to their own nested directory we would need to update our module specifier to take into account the new folder structure.

Image description

All of these examples have started with "./" since the subdirectories are in the same folder as the consuming code, but that might not always be the case. Let say that some code wants to import code from a sibling level directory. While “./” can be used to access the current directory, “../” will access one directory higher.

In the example below, the circle that lives in the operations folder is able to import a file from the constant folder by using "../" to navigate outside of its current directory. That will take it to the calculator directory, where it can access the constants directory.

Image description

This can be done recursively as needed. The deeper the consuming code is relative to the needed code, the more "../" are used. You can combine these like "../../", which would take you two directories higher.

A good way to think about it is that "./" puts you in the directory of the current file. "../" takes you one directory higher. These patterns can be combined to access and expose code as needed.

In the next post I'll cover a few more module specifier patterns.

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (0)

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay