When working on a Node.js project, managing module imports can become a cumbersome task. Thanks to TypeScript and its tsconfig.json
configuration file, you can use the paths
option to simplify the process of importing modules. This feature allows you to define custom aliases, making the import
or require
instructions much more readable. At the same time, Node.js does not support that feature out of the box.
In this tutorial, you will learn how to use tsconfig.json
‘s paths
option in Node.js through the tsconfig-paths
package. Time to make module management more efficient and maintainable!
Why ts-node Does Not Support Paths
Suppose your tsconfig.json
file contains the following code:
{ "compilerOptions": { "target": "es6", "module": "commonjs", "lib": ["es6"], "strict": true, "esModuleInterop": true, "outDir": "./build", "sourceMap": true, "paths": { "@/*": ["./src/*"] } }, "include": ["src/**/*.ts"], "exclude": ["node_modules", "**/*.spec.ts"] }
Note the paths
option, which allows you to specify a set of aliases that re-map imports to lookup locations. This makes the require/import
instructions in your code easier to read, as below:
import * as Constants from "@/constants" import express from "express" const app = express() app.get("/hello-world", (req, res) => { res.json(Constants.HELLO_WORLD_MESSAGE) })
Note how elegant the first import
instruction is compared to something like this:
import * as Constants from "./../../constants"
paths
are cool, but unfortunately Node.js does not support them. Let’s understand why!
In TypeScript, modules are resolved similarly to the way Node.js does. However, the paths
option allows you to specify arbitrary module paths that don’t start with /
or .
. These special aliases can be mapped to physical paths on the file system, which the TypeScript compiler can resolve from the tsconfig.json
file. So, TypeScript will be able to compile the code successfully.
However, when trying to run files compiled ts-node
, they will only look for modules in the node_modules
folders up to the root of the file system. As a result, modules specified by paths
in tsconfig.json
will not be found and the Node.js server will fail with the following error:
Error: Cannot find module '@/contants'
Luckily, there is a solution and it is called tsconfig-paths
. Time to learn how to configure it to make paths
works in ts-node
!
Using paths in ts-node With tsconfig-paths
tsconfig-paths
is an npm library that allows ts-node
to load modules imported using the aliases defined in the paths
section of tsconfig.json
.
Add it to your project’s dependencies with:
npm i tsconfig-paths
Then, update the command to launch your ts-node
project as follows:
ts-node -r tsconfig-paths/register index.ts
Where index.js
is your Node.js main TypeScript file.
Et voilà! The “Cannot find module” error is now gone and your ts-node
project is working with paths
aliases.
At the same time, if try to compile your TypeScript code with tsc
and then launch it with node
, you will still get a “Cannot find module” error. tsconfig-paths
works like a charm with ts-node
but still have some issues with node
.
As you can read on the official GitHub page of the issue, there are several workarounds to address the problem. An effective solution is to change the Node.js start command of the tsc
compiled code to:
node -r ts-node/register/transpile-only -r tsconfig-paths/register build/index.js
Where build/index.js
is the path to the main Node.js file in your outDir
folder.
If you are worried about using ts-node
in production, note that ts-node/register/transpile-only
does not introduce significant performance overhead.
Congrats! Error fixed!
Conclusion
In this article, you saw what paths
are, how to configure them in tsconfig.json
, why Node.js does not support them, and how to address this issue. Specifically, you learned that the tsconfig-paths
library can help you make Node.js work with imports involving aliases defined in paths
.
Thanks for reading! I hope you found this article helpful.