Skip to content
This repository has been archived by the owner on Sep 2, 2023. It is now read-only.

import from global node_modules at NODE_PATH with --input-type=module #534

Closed
cmonacaps opened this issue Jul 21, 2020 · 4 comments
Closed

Comments

@cmonacaps
Copy link

cmonacaps commented Jul 21, 2020

Hi,

I found that while

  • spawning [email protected] with --input-type=module
  • writing a script to its stdin that does import * as R from 'ramda' or import R from 'ramda'
  • having ramda installed globally and env NODE_PATH set, I think, properly

I get an error, ERR_MODULE_NOT_FOUND when the script piped into node tries to import.

$ cd /tmp/working_dir
$ /usr/local/bin/useless_ramda_script
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'ramda' imported from /private/tmp/working_dir/[eval1]
Did you mean to import ramda/src/index.js?
    at packageResolve (internal/modules/esm/resolve.js:594:9)
    at moduleResolve (internal/modules/esm/resolve.js:633:14)
    at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:726:11)
    at Loader.resolve (internal/modules/esm/loader.js:82:40)
    at Loader.getModuleJob (internal/modules/esm/loader.js:226:28)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:51:40)
    at link (internal/modules/esm/module_job.js:50:36)
    at processTicksAndRejections (internal/process/task_queues.js:93:5) {
  code: 'ERR_MODULE_NOT_FOUND'
}
>echo $NODE_PATH
/Users/username/.nvm/versions/node/v14.5.0/lib/node_modules
>ls $NODE_PATH 
node-esm	npm		ramda

I'm a bit puzzled what the source of the problem is, it seems to center on resolving esm modules but also perhaps the env plays a part, because from the development directory of the node-esm project, it works ok to run node index.js /usr/local/bin/useless_ramda_script, perhaps in that case it's using the ramda installed in that package rather than the global one. There are a lot of experimental parameters to influence the import behavior in node, and, there are a lot of ways to spawn the script from node-esm, I tried a few which are still present in the code in unused subroutines makeFutureSpawnScript and makeFutureVm as well as the one that seemed to work best so far, makeFutureSpawnPipe.

See full source code at https://github.com/cmonacaps/node-esm

Asides, does node support import * as X from 'package'? Am I going to have to have node-esm run babel on the script to get this working?

@ljharb
Copy link
Member

ljharb commented Jul 21, 2020

Yes, node certainly supports that syntax.

However, ESM doesn’t support NODE_PATH - which has been discouraged (by the community, if not node itself) for many years. You can import things installed locally, in node_modules, or relative files.

@cmonacaps
Copy link
Author

Perhaps a package.json could be synthesized on the fly, where the ./node_modules symlinks to $NODE_PATH. One problem I can see is that it depends on the current working directory but more often you'd want to run a /usr/local/bin/ script within the current cwd for whatever it is you're trying to do. Maybe it's possible to cwd for the script loading and then cwd back to original directory to run it. But I think evaluation is loading and running as far as I can tell. 🤔 thanks for the response.

@bmeck
Copy link
Member

bmeck commented Aug 4, 2020

@cmonacaps a workaround to avoid needing to use NODE_PATH is at the old proposal doc and does not require synthesizing a file at runtime . NODE_PATH style mutable resolution algorithms has been deprecated and is not directly being looked at for support. Another alternative is to write a --loader which does allow creation of such an algorithm. Closing for now as we have a couple of mitigation strategies. Feel free to re-open if there is a reason none of them work due to API design.

@bmeck bmeck closed this as completed Aug 4, 2020
@cmonacaps
Copy link
Author

Ok Thanks for the update and link to the workaround.

I think, for what I was trying to achieve, it's just as well to create fewer and better-developed scripts which are themselves packaged global installs, with their dependencies stated and installed as such, using the package.json bin entry to define the CLI commands instead of script files located in /usr/local/bin.

It might have been easier to get there from the way I was headed, but otoh I notice when using nodejs that I never see the global/host-configuration dependency conflicts I've seen with other common interpreted languages that do support this kind of workflow. I'm just speculating that this is the reason this approach is, per your link for example, discouraged.

That there is a global node_modules, and that it works if using require instead, suggests it's more nuanced or at least the thinking's evolved over time on how this should or shouldn't be done.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants