Smelly Code

How to "require" with aliases πŸ”

May 8, 2021

I recently worked on a NodeJs based command-line app. The app had significant depth in its directory structure. The depth in directory structure unintentionally added a wild amount of relativeness to require statements.

const { utils } = require('../../../../lib');
const commands = require('../../../commands');

When I encountered these statements, I realized the need of aliases. I search for nodejs require aliases and landed on the gist: Better local require() paths for Node.js. It recommended almost 8 different solutions. I found the alias approach more promising and convincing because of following reasons:

  • Clean cross platform solution.
  • Uses a well maintained popular npm package: module-alias.
  • Aliases can be prefixed with symbols(such as @) to tip off fellow developers.

The alias approach had a few downsides which could be resolved easily.

  • Littering package.json with aliases(can be avoided by manually adding aliases).
  • Requires additional steps for linter and editor.

After evaluating trade offs, I installed module-alias and added aliases in package.json.

{
"_moduleAliases": {
"@lib": "lib",
"@constants": "constants",
"@commands": "commands"
}
}

I also replaced relative require statements with aliases and tested the change.

const { utils } = require('@lib');
const commands = require('@commands');

Things were working as expected. But gradually ESLint started screaming:

It was expected because EsLint can not resolve the path aliases. I pacified ESLint using eslint-import-resolver-alias with below config:

{
"import/resolver": {
"alias": [
["@lib", "./lib"],
["@constants", "./constants"],
["@commands", "./commands"]
]
}
}

After a while, I found that features such as IntelliSense, quick navigation between modules, etc. stopped working for aliased paths. It’s because VS Code was not aware of the aliased path mappings. I added the aliased path mappings to compilerOptions of jsconfig.json for VS Code.

{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@lib": ["./lib"],
"@constants": ["./constants"],
"@commands": ["./commands"]
}
}
}

It started working as usual. Tada πŸŽ‰! I was happy. EsLint was happy. VS Code was happy. Everyone was happy.


Hitesh

Hi, I am Hitesh.

I build things and ship some of them.