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.