Sponsored

How to Configure Typescript baseUrl in a Node.js Project

Jasser Mark Arioste

Jasser Mark Arioste

How to Configure Typescript baseUrl in a  Node.js Project

Hello, hustlers! In this tutorial, you will learn how to configure baseUrl option in Typescript to enable absolute imports for your code. 

Sponsored

The Problem#

If you want clean code, one of the practices is to use absolute imports in a NodeJS typescript project. by using the baseUrl option in your tsconfig.json file. You could turn this:

import MyService from "../../services/MyService"
1

Into this:

import MyService from "services/MyService"
1

In VS Code it would work absolutely perfectly.

However, when I built my code using tsc command and ran it using node ./dist/index.js, I got this error:

$ node ./dist/index.js
node:internal/modules/cjs/loader:936
  throw err;
  ^

Error: Cannot find module 'services/MyService'
Require stack:
- D:\Blog\typescript-absolute-imports\dist\index.js
1234567

This happens because javascript does not recognize absolute imports. If we check the outputted js files, the tsc command doesn't transform the path to relative imports:

// dist/index.js
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
exports.__esModule = true;
var MyService_1 = __importDefault(require("services/MyService"));
console.log(new MyService_1["default"]());
12345678
Sponsored

Configuring baseUrl for Production#

To configure baseUrl for production and fix the "Cannot find module" error,  you need to use the tsc-alias package. There might be other ways to solve this, but I find this approach straightforward and simple.

Suppose you have the following project structure:

|- /dist
|- /node_modules
|- /src
   |- index.ts    
|- package.json
|- tsconfig.json
12345

Step 0: Configuring tsconfig.json

All source code is located inside the/src folder and will be outputted to the /dist folder after the build.  First, configure your tsconfig.json to use baseUrl:

// tsconfig.json
{
  "compilerOptions": {
    "module": "CommonJS",
    "outDir": "./dist",
     //...other options
    "baseUrl": "./src"
  }
}
123456789

Step 1: Installing tsc-alias package

Next, let's install the tsc-alias package:

yarn add -D tsc-alias
# or
npm i -save-dev tsc-alias

Step 2: Modifying package.json

Next, let's modify package.json to include tsc-alias in the "build" script. This will transform the absolute paths into relative paths after the tsc command which completely solves our problem.

{
  ...
  "scripts": {
    "build": "tsc && tsc-alias",
    "start": "node ./dist/index.js",
  },
  "devDependencies": {
    "tsc-alias": "^1.7.1",
    "typescript": "^4.9.3"
  }
}

Step 3: Testing

Finally, let's test our script using yarn build and yarn start

$ yarn build
yarn run v1.22.17
$ tsc && tsc-alias
Done in 1.61s.

$ yarn start
yarn run v1.22.17
$ node ./dist/index.js
Hello, MyService
MyService {}
Done in 0.09s.

Yahoo! There are no errors! Next, let's check the outputted files inside dist/index.js:

// dist/index.js
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
exports.__esModule = true;
var MyService_1 = __importDefault(require("./services/MyService"));
console.log(new MyService_1["default"]());
12345678

It's now using relative import, not bad.

With this, we have configured the baseUrl option for production. What about development?

Sponsored

Configuring baseUrl for Development#

For development, I like to use the ts-node-dev and tsconfig-paths packages to solve the absolute import problem.  First, let's install both packages:

yarn add -D ts-node-dev tsconfig-paths
# or
npm i --save-dev ts-node-dev tsconfig-paths

Then, add a "dev" script to our package.json file:

{
  "scripts": {
    "dev": "ts-node-dev -r tsconfig-paths/register ./src/index.ts"
  }
}

Make sure you adjust if you have a different path for your index.ts file.

Finally, you can run yarn dev command: 

$ yarn dev
yarn run v1.22.17
$ ts-node-dev -r tsconfig-paths/register ./src/index.ts
[INFO] 16:47:13 ts-node-dev ver. 2.0.0 (using ts-node ver. 10.9.1, typescript ver. 4.9.3)
Hello, MyService
MyService {}
Done in 2.00s.
Sponsored

Conclusion#

We learned how to configure the baseUrl option from scratch. If you're building an express or a GraphQL server using typescript, I believe this will help you a ton. I also created a GitHub repo to support this approach.

If you like this tutorial, please leave a like or share this article. For future tutorials like this, please subscribe to our newsletter or follow me on Twitter.

Sponsored

Resources#

Sponsored

Related Posts#

Credits: Image by Yuri from Pixabay

Share this post!

Related Posts

Sponsored

Subscribe to our newsletter

Get up-to-date on latest articles on react.js, node.js, graphql, full-stack web development. No Spam. Helpful articles to improve your skills. Sent directly to your inbox.