The "Relative path hell" Problem
Typing out long and error-prone paths to your Node JS modules can be a daunting task!
Even with code-completion features like IntelliSense in place (which is supported by almost every IDE or text editor), this can become more challenging as your codebase grows.
Just imagine changing the directory structure of your project and you're forced to change all occurrences of the modules currently being referenced multiple times throughout your project. It's a maintenance nightmare!
Moreover, it looks damn ugly!
An alias to a module path clearly indicates the location and purpose of the module being used. Dots and slashes hardly tell anything!
There might be a possible solution to this "relative path hell" problem -
A Symlink or a Symbolic Link is simply a shortcut or a reference to another file. It is a file that points to another file.
Basically, you can create symlinks to your modules and have your Node JS app refer to these modules using the created symlinks.
Symlinks can be created using the ln command available on Linux/UNIX/Mac. If you're not already on Windows 10 then you're probably not leveraging the linux bash shell that comes bundled with it (more info), in that case, you can use the standard Windows mlink command.
But wait a minute, you don't actually have to manually create all these symlinks by yourselves. Instead, you can write a simple Node JS script which can automate the symlink creation process for you. The Node JS file system module exposes the fs.symlink method which can be used for creating symlinks for directories or files.
There's an existing NPM package which can do this job for you called link-module-alias.
Simply add the required module aliases into your project's package.json file and add a postinstall script, which will automatically initialise the symlink creation process for you.
After your configuration is complete, simply run -
npm install - Installs your project's dependencies and automatically executes the postinstall script.
npm run postinstall - Only executes the postinstall script.
Once the postinstall script executes, it makes a call to link-module-alias which creates the required symlinks for your project. Your Node JS app will then be able to resolve all references to the defined aliases.
Now whenever you are requiring your modules, you can simply do this -
No matter where you are in your project tree, all your aliased modules will resolve successfully.
The icing on the cake
If you happen to use VS Code then all of your aliased modules and directories will have their files appear in the VS Code autocompletion drop-down, which makes it super handy to use your aliased modules!
Another plus point to be mentioned here is that this particular approach doesn't need any runtime hooks in your app's entry point, unlike other approaches to solve this problem which rely on runtime hooks. Runtime hooks add a level of unnecessary computation and complexity to your app. If by any chance a runtime hook fails, it might crash your entire app.
Update (2021): Subpath Imports
Support for subpath imports was added in Node JS v14.6.0, v12.19.0 which helps in the creation of import maps that only apply to import specifiers from within the package itself. Entries in the imports field must always start with # to ensure they are disambiguated from package specifiers.
If you have no issues with require hooks then you can consider this package - module-alias. There are a few gotchas though that you'll need to keep in mind while using this package. For example, this package modifies the default require behavior! And should be used with caution.
The babel module resolver plugin can be used with the babel transpilation pipeline to resolve modules with custom aliases for directories or specific files.