Node: Add default module search paths to package.json

Created on 3 Oct 2017  路  15Comments  路  Source: nodejs/node

I'm using TypeScript, with my source files in src/ and outputting to dist/. I have modules in src/modules/ and some other stuff in src/scripts/. The directory structure is maintained when TypeScript transpiles to JavaScript in dist/. However, the import... statements are transpiled to require() statements with the (non-relative) paths unchanged.

In TypeScript, I can refer to my modules without having to use messy relative paths by setting baseUrl in tsconfig.json. If I set it to ./src, I can then import my modules with something like:
import * as myModule from "modules/myModule";

However when that is transpiled to the Node.js equivalent:
const my_module_1 = require("modules/myModule");

... Node.js doesn't find the module because the file pulling in the module is in src/scripts. Wouldn't it be nice if you could just add module search paths to the beginning of Node's paths list by just having a moduleSearchPaths property in package.json (@refack suggested using .npmrc instead)? Then the first place Node would search would be those paths and I could just say:

    ...
    "moduleSearchPaths": [
        "./dist"
    ]
    ...

... making Node first search for dist/modules/myModule.js - and it would work.

By the way, I know you can set the NODE_PATH env variable to do this but I think that's a nasty solution because I always try to avoid using env variables. They don't translate well between different environments.

feature request module

Most helpful comment

My understanding is that NODE_PATH=./path/to/somewhere node file.js is the only practical means of specifying a path.

I do this because

const myModule = require('static-path-to/my-module')
````
is much cleaner than 
```javascript
const myModule = require('../../../../../omg/../relative-path-to/my-module')

which is brittle because it may break when the containing file moves or when copied to another file; and it just looks terrible.

If NODE_PATH is going away, we need an equivalent. A --node_path="./path/to/somewhere" flag or a "paths": "./path/to/somewhere" package.json key/value would work just fine in my case. Either would also work for Windows unlike my current solution. See https://github.com/nodejs/node-v0.x-archive/issues/4609 by @ForbesLindesay.

All 15 comments

I think this is unlikely to gain traction because I see this as a similar request brought up during the ES modules implementation discussion(s), which was voted down by the TSC. I think this just unnecessarily complicates the lookup algorithm even further, when the lookup algorithm is already fairly complicated.

So there's literally no way to get away from relative paths? This seems like a really basic issue to me.

There is a way that I've used a few times. You can create a src/node_modules directory and put your files in it.

Yeah that does work. Feels like a hack though. People will think it should be for NPM modules.

It's not really a hack though - node_modules is a _node_ thing. npm just happens to install to it so that things work out of the box.

But is it really a good idea to dictate that you have a src/node_modules directory structure rather than have what you want and point to it?

Yes, IMO. It means there is One And Only One Way to do it.

Right now the rule is 'look in node_modules' and every developer knows that.

Except that it isn't because it looks in a bunch of different places including the NODE_PATH variable.

@jez9999 NODE_PATH is deprecated and does not work w/ ESM loader. If someone is relying on it you should feel encouraged to tell them to move off of it.

And switch to having a second ugly node_modules directory in their source tree. Not exactly something I can recommend either.

I have to agree with @jez9999. I can see some of the philosophical/implementation issues with a package.json configurable paths option, but it seems like a common issue that many devs have with Node, no? And it likely _is_ solvable by smarter minds than mine? In any case, would be a fantastic feature for a common usecase!

My understanding is that NODE_PATH=./path/to/somewhere node file.js is the only practical means of specifying a path.

I do this because

const myModule = require('static-path-to/my-module')
````
is much cleaner than 
```javascript
const myModule = require('../../../../../omg/../relative-path-to/my-module')

which is brittle because it may break when the containing file moves or when copied to another file; and it just looks terrible.

If NODE_PATH is going away, we need an equivalent. A --node_path="./path/to/somewhere" flag or a "paths": "./path/to/somewhere" package.json key/value would work just fine in my case. Either would also work for Windows unlike my current solution. See https://github.com/nodejs/node-v0.x-archive/issues/4609 by @ForbesLindesay.

At the top of your script, use the following to add a new search path for modules search.
module.paths.push('[MEW_PATH');

For example:
module.paths.push('../../../../../omg/../relative-path-to');
const myModule = require('my-module')

@RoyeA I presume, it'll work for scripts, but not for programs. module is not a global but a local-per-module.

On the other hand, if it was truely global (like NODE_PATH), it'll lead to broken code in other modules just because they're may be unaware of that certain path modification.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

benjamingr picture benjamingr  路  135Comments

speakeasypuncture picture speakeasypuncture  路  152Comments

aduh95 picture aduh95  路  104Comments

yury-s picture yury-s  路  89Comments

ctavan picture ctavan  路  87Comments