Nest JS Module aliasing using module-alias

A Simple Way To Use Path Aliases in NestJS

I am talking about this

Original:
import CatModule from '../../cat/cat.module.ts'
Alias Path:
import CatModule from '@/cat/cat.module.ts'

whenever we write code most of teh times we end up using whole path which is pain as we have to traverse the whole path Solution for that is module-alias and we will us ethat with nestjs app, i hope you already know hoe to create basic nestjs app using CLI

Nest.js Application Let’s continue with NestJS! We are going to install the NestJS CLI, so open the terminal of your choice and type:

$ npm i -g @nestjs/cli

We initialize a new NestJS project with its CLI. That might take up to a minute. The “-p npm” flag means, that we going to choose NPM as our package manager. If you want to choose another package manager, just get rid of this flag.

$ nest new nest-alias -p npm

Furthermore, we’re creating a PlayerModule, PlayerController, and a helper function in a different destination.

$ nest g mo player && nest g co player --no-spec
$ mkdir src/common && mkdir src/common/helper
$ touch src/common/helper/utils.helper.ts

After this command is done you can open your project in your code editor. Since I use Visual Studio Code, I gonna open the project by typing:

$ cd nest-alias
$ code .

Now lets follow what all you need to have module-path alaising

Step-1

Looks at this NPM package https://www.npmjs.com/package/module-alias Install

npm i --save module-alias

Usage Add your custom configuration to your package.json (in your application's root)

// Aliases
"_moduleAliases": {
  "@root"      : ".", // Application's root
  "@deep"      : "src/some/very/deep/directory/or/file",
  "@my_module" : "lib/some-file.js",
  "something"  : "src/foo", // Or without @. Actually, it could be any string
}

// Custom module directories, just like node_modules but with your private modules (optional) "_moduleDirectories": ["node_modules_custom"],

Then add this line at the very main file of your app, before any code

require('module-alias/register')

And you're all set! Now you can do stuff like:

require('something')
const module = require('@root/some-module')
const veryDeepModule = require('@deep/my-module')
const customModule = require('my_private_module') // module from `node_modules_custom` directory
 
// Or ES6
import 'something'
import module from '@root/some-module'
import veryDeepModule from '@deep/my-module'
import customModule from 'my_private_module' 

we can do the same for our project npm i --save module-alias

Step-2

Update your tsconfig file to have path mapping there

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es2017",
    "allowJs": true,
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "strict": true,
    "skipLibCheck": true,
    "paths": {
      "@app/*": ["src/app/*"],
      "@auth/*": ["src/app/auth/*"],
      "@domain/*": ["src/app/domain/*"]
      "@test/*": ["test/*"]
    }
  },
}

Step-3

Add same path level configuration to jest.config.ts and jest.config-e2e.js as tests also needs to resolve module using path alias jest.config.js

module.exports = {
  setupFiles: ['<rootDir>/test/setEnvVars.js'],
  silent: false,
  moduleFileExtensions: ['js', 'ts'],
  rootDir: '.',
  testRegex: '[.](spec|test).ts$',
  transform: {
    '^.+\\.(t|j)s$': 'ts-jest',
  },
  coverageDirectory: './coverage',
  testEnvironment: 'node',
  roots: ['<rootDir>/'],
  moduleNameMapper: {
    "^@app(.*)$": "<rootDir>/src/app/$1",
    "^@auth(.*)$": "<rootDir>/src/app/auth/$1",
    "^@domain(.*)$": "<rootDir>/src/app/domain/$1",
  },
};

jest-config.e2e.js

// For a detailed explanation regarding each configuration property, visit:
// https://jestjs.io/docs/en/configuration.html

module.exports = {
  "setupFiles": ["./test/setEnvVars.js"],
  moduleFileExtensions: ["js", "json", "ts"],
  rootDir: ".",
  maxWorkers: 1,
  testEnvironment: "node",
  testRegex: ".e2e-spec.ts$",
  transform: {
    "^.+\\.(t|j)s$": "ts-jest",
  },
  moduleNameMapper: {
    "^@app(.*)$": "<rootDir>/src/app/$1",
    "^@auth(.*)$": "<rootDir>/src/app/auth/$1",
    "^@domain(.*)$": "<rootDir>/src/app/domain/$1",
  },
  globals: {
    "ts-jest": {
      tsconfig: "tsconfig.e2e.json",
    },
  },
};

Step-4

now we can introduce this path alsing to our package JSON which is important as our application need to resolve @config, @domain, @app using path-aliasing

  "_moduleAliases": {
    "@app": "dist/src/app",
    "@auth": "dist/src/app/auth",
    "@domain": "dist/src/app/domain"
  },
  "devDependencies": {
  }

Finally how to let application know about loading all these alsing using module-alias module

Step-5

require("module-alias/register");
require('dotenv').config();

Now i can use these aliasing everywhere in project inside src/ or tests

Step-6

import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { EventEmitterModule } from '@nestjs/event-emitter';
import { TerminusModule } from '@nestjs/terminus';
import { LoggerModule } from 'nestjs-rollbar';
import { ConfigModule } from '@config/config.module';
import { DbModule } from '@db/db.module';
import { KafkaModule } from '@kafka/kafka.module';
import { AppLoggerModule } from '@logger/logger.module';

Conclusion

Module aliasing is useful and you must use this in your project, to follow this just use all these steps and you should be able to use alising for custom modules, you can addyour own path just add new module path entry in all files

References

Comments