`npm link` sub-package
I've been trying to resolve an "invalid hook call" error caused by duplicate versions of React. One of the recommended solutions is to run npm link ../myapp/node_modules/react from inside mylib.
Because Volta doesn't support the relative path syntax for npm link (cf #956), I tried running the two commands separately:
-
cd path/to/myapp/node_modules/react && npm link -
cd path/to/mylib && npm link react
Unfortunately, the first command fails with the following error:
"C:\\Program Files\\Volta\\npm.exe" "link"
Volta v1.0.2
Could not read package.json manifest for myapp
Please ensure the package includes a valid manifest file.
Error cause: The system cannot find the path specified. (os error 3)
It seems that Volta doesn't like that I'm running npm link inside a sub-directory of myapp/ Maybe it thinks I'm trying to link myapp instead of myapp's react dependency? 🤷
Hi @axelboc, that's an interesting use-case. I think in this situation you're running into the fact that Volta will ignore package.json files inside of node_modules, since what we care about (generally speaking) is the version that was used by the installer, which comes from the root project. So I suspect that approach isn't going to work generally ☹️ The best solution will likely be for us to get #956 fixed so that it works properly, after which you shouldn't need to worry about those issues.
Separately, we may also be able to adjust our parsing logic to handle npm link within a node_modules directory in the same way that npm does.
As a workaround, I've been using a different npm. I'm on macOS using homebrew and running /opt/homebrew/bin/npm link.
Why does Volta change how npm cli works, does it do more than install it?
@tim-phillips There are a number of interrelated reasons that all boil down to: We have to do something otherwise npm link won't work at all. To go into more depth:
Volta's core approach is that the versions (Node, npm, & yarn) should be declarative, so that each project can declare the tools it needs and users can simply switch between them without having to remember to reload the environment (or add anything to slow down their shell experience on every cd). However, npm by default puts global installs and links into a subdirectory of itself. This means that a call to npm link is only valid for one specific npm version.
If two projects had different Node or npm versions, then it wouldn't be possible to link between them, since the outgoing link from one would be tied to its npm version, while the incoming link wouldn't be able to find the directory associated with a completely unrelated npm version. This was the case for a long time with Volta, and led to very confusing and non-obvious errors since Volta's declarative nature made the version switching less explicit (see https://github.com/volta-cli/volta/issues/56 for the start of the discussion).
To work around that, Volta moves all of the global installs (and links) to a separate, shared directory, so that we can properly connect packages even if they aren't using the exact same npm version. This is done by detecting those situations and using the prefix configuration setting to point outside of npm's internal directory. To make all of that work, the interception requires Volta to know more about what package is being linked.
Note: Unlike npm, yarn by default uses a directory outside of itself (~/.config/yarn I believe), so yarn link works across versions already, without any extra shenanigans.
Is there a workaround to link packages using Volta? My workaround is using Yarn, but would like to keep everything in one tool.
@Qocotzxin
As a workaround you can just use the file:/ option inside package.json
For example a module in package.json could be:
"jsonwebtoken": "^8.5.1"
You can download jsonwebtoken and make local and link it like this:
"jsonwebtoken": "file:/User/user.name/dev/jsonwebtoken"
Then delete the remote module and run npm install again
rm -rf node_modules/jsonwebtoken && npm install
If the local module is with typescript you will have to to run npm build after every change in order to reflect the changes in the dependant application.
Nothing new to fix this ?
It still doesn't work
same problem here, using volta 1.1.1