Avoiding require('../../../relative/path') hell in Node.js
A frequent problem that you might run into in your Node.js application is requiring your local dependencies using a relative path notation. I.e., similar to require('../../../config/app'). This can soon become confusing, error prone and a huge productivity loss trying to hit the right level of directory structure.
The most elegant way that I have come across so far is an npm package module-alias.
With the package installed, I can then configure aliases like @app and @root that makes local dependency locations manageable and much more pleasant to interact with.
To configure, install the package as usual:
npm i module-alias --save
As the first line of your program entrypoint, i.e, index.js or server.js, register the package:
require('module-alias/register')
Aliases are defined in package.json, as follows:
"_moduleAliases": {
"@app": "./src",
"@root": "."
},
This setup now allows you to refer to your local dependencies as:
const userRoutes = require('@app/routes/user')
// or using import
import User from '@app/models/User'
That works for your server-side application. What about client? Fortunately, this package can also be used with Webpack, which allows use of alias via its resolve configuration. An example configuration webpack.config.js snippet is below:
const packageJson = require('./package.json')
let webpackConfig = {
// ...
resolve: {
alias: packageJson._moduleAliases
},
// ...
}
This pulls in the same alias definitions from package.json. From that point, you can refer to client-side dependencies also with the same @app/path/to/file syntax.
If you are using less-loader with Webpack resolver, the syntax for @imports are as below example (Note the preceding ~, which enables less-loader version 4 and above to resolve using Webpack's resolver):
@import (reference) "~@app/styles/mixins/buttons.less";
Hope that helps. If you are aware of a better pattern, please share via comments below.