Writing relative imports in Node.js is something I tend to avoid especially when it's growing larger in functionality. However, For something this basic yet it's so hard to get right. There are just many ways of doing that on the internet.
There are many ways to avoid relative imports in Node.js. One of them is either:
- Add
NODE_PATH=./
env ( reference ) - Set
"baseUrl"
in(js|ts)config.json
( reference ) - Use
require.main.require
( reference ) - Directly write into
node_modules
( reference ) - Use NPM/Yarn workspaces ( reference )
There are many downsides to each approach.
- Adding an environment variable requires adding
cross-env NODE_PATH=./
to allpackage.json
scripts and every time you need to run the script yourself. This behavior is also somewhat unreliable during my testing, also VSCode Intellisense won't understand what you're trying to import. - The
baseUrl
option from(js|ts)config.json
seems to work out of the box, only for VSCode Intellisense. Node.JS won't understand them so I need a babel compiler to set up, it's explained here anyway but to me, this is way too complicated. - Using
require.main.require
seems like a hack to me, it enforces me to use that in all the scripts rather than the usualrequire
, which of course it's something that I don't like. - Directly writing to
node_modules
is something against its purpose, also would you rather be willing to move your scripts to mode_modules? I wouldn't want it. It would become a nightmare to maintain. - Using NPM/Yarn workspaces seems promising at first glance but it enforces me to thinking in the way it was designed for "monorepo". Monorepo is good if you have multiple projects that share code, but really it's just too much because I just work on one big node app. Note this was Yarn only feature, NPM add support too but my last experience using it was buggy.
I have found a less popular but way more reliable: symlink-dir
. Let's me summarize their explanation on NPM:
Lets suppose you'd like to self-require your package. You can link it to its own node_modules:
symlink-dir . node_modules/my-package
What is by mean to "link"? It's basically creating a directory shortcut. You can read it more here. NPM/Yarn workspaces internally also doing this way.
So to use symlink-dir
, I just need to add these values in package.json
:
{
"scripts": {
"postinstall": "symlink-dir src node_modules/src",
},
"dependencies": {
"symlink-dir": "latest"
}
}
This creates a symlink from src
folder to node_modules
in my project. After npm i
I can use require('src/module.js')
instead of require('../../../src/module.js')
. Works with ESM imports too!
You can also add more symlinks by just appending the postinstall
like "symlink-dir src node_modules/src && symlink-dir lib node_modules/src/libraries"
and redoing npm i
. Out of all solutions previously, this method works best to me. Hope you like it too!
Top comments (0)