lerna: npm uninstall throws 404 for unpublished siblings
Take the following project dependency structure
.
├── packages
├── module-a
├── dependency-a (3rd party and published on npm)
└── module-b (sym link dependency from a `lerna bootstrap`)
└── module-b (private/not published on npm)
cd
’ing into module-a and attempting to uninstall dependency-a:
npm uninstall dependency-a
Gives the following error:
npm ERR! code E404
npm ERR! 404 Not Found: module-b@v1.0.0
For some reason (guessing clean up), NPM re-evaluates the dependent packages on a uninstall
which blow’s away any sym links resulting in this 404?
Potentially related to: https://github.com/npm/npm/issues/17025
Expected Behavior
I would expect dependency-a to uninstall and module-a packages.json/lock
files to update.
Current Behavior
npm uninstall behaviour is exited and the module is not removed.
Possible Solution
Open an issue with NPM? Find or document a work around.
Your Environment
Executable | Version |
---|---|
lerna --version |
5.4.2 |
npm --version |
5.4.2 |
node --version |
8.7.0 |
OS | Version |
---|---|
macOS Sierra | 10.12.6 |
About this issue
- Original URL
- State: open
- Created 6 years ago
- Reactions: 19
- Comments: 15 (7 by maintainers)
Links to this issue
Commits related to this issue
- re bootstrap lerna with advice from https://github.com/lerna/lerna/issues/1229 — committed to ghinks/epl-ml-mono-repo by ghinks 5 years ago
@aweber1 Thanks, that’s good to know. I kinda dry-coded my bullet points 😅
I’m planning on implementing
lerna remove
andlerna upgrade
, since lerna is now a monorepo itself and the pain is felt directly.When working with lerna-managed packages, running npm commands directly in a managed directory (
packages/*
be default) is not guaranteed to work. It is not an npm bug, either, becauselerna bootstrap
is doing special things to the package.json when installing (to workaround the local packages, basically).Currently, removing a dependency in a lerna-managed package requires manual editing of package.json and re-running
lerna bootstrap
from the root. (contrary to the best practice, which is indeednpm rm
/uninstall
)In the future I hope to add a
lerna remove
subcommand that streamlines this process.@jennasalau My apologies, I forgot a step. I have been using
--hoist
so long, I forgot the patterns when npm actually installs stuff in every package directory (which is pretty slow compared tolerna bootstrap --hoist
, even with zippy npm these days).Anyway: Run
lerna clean --yes --scope module-a
before re-runninglerna bootstrap
.The normal behavior of npm recognizing changes to package.json and manipulating package-lock.json to match will be restored when
lerna clean
nukes thenode_modules
. Turns out we have an over-eager optimization inlerna bootstrap
that is attempting to save time avoiding a “no-op” install, and we’re not respecting npm’s ability to also make that judgement (and remove the deleted dependency).Once again, my apologies. Thank you for having the patience to document a workaround! We (I, actually) could really use help implementing the
lerna upgrade <dependencyName>
andlerna remove <dependency>
subcommands. Even documentation would be appreciated.Teaching people in a team to run multiple command to just remove one package is an extra overhead 😢. Is it in plan to implement this anytime soon? @evocateur
If we stopped mangling the package.json files so badly during bootstrap, we would have a better story. Also, supporting the relative
file:
protocol (which would require resolution during publish) would make it all “just work”, for the most part.To instruct folks that manually editing package.json files is the “best practice” for modifying dependencies goes against my strongly-held belief that you should always use the various npm subcommands when doing those sorts of things. I realize it is certainly possible to manually edit and get (mostly) what you expect in a normal npm package scenario, but in my experience it is a lot more brittle and prone to breakage. Lerna definitely changes the context significantly.
Here are the bullet points, such as they are:
To remove • Edit the target package.json, removing the dependency • Run
lerna bootstrap
in the rootTo add • If hoisting,
npm i <dependency>
in root • Edit the target package.json, adding the dependency (if hoisting, just copy the line from the modified root package.json) • Runlerna bootstrap
in the rootTo upgrade (semver major): • If hoisting,
npm i <dependency>@latest
in root • Edit the target package.json files, upgrading the dependency version (if hoisting, just copy the line from the modified root package.json) • Runlerna bootstrap
in the rootTo update (when package-locked): • Same as semver major upgrade, except when hoisting, call
npm up <dependency>
in root instead of install.Manually linking local packages has become a pain.
The stale bot seems to be disregarding my commands. Such is the inevitable end with robots, it seems.
Coming back to lerna + npm from yarn workspaces this is a rather big surprise. Uninstalling/installing in packages seems like such a core task of a mono repo manager.
Most annoying is to have to update package.json files manually, lookup version numbers, etc.
npm install
does this automatically for you but using lerna renders this unusableThanks for the bullet points! For the “remove”, however, I ended up having to do this:
(using example module name “my-module”)
my-module/package.json
, removing the dependency from eitherdevDependencies
ordependencies
lerna clean --yes --scope my-module
lerna bootstrap
in the rootusing v2.9.0 and not using hoisting
Hmm you would also have to manually remove it from the
package-lock.json
file and the bloody reference gets entwined everywhere. Its actually a nightmare removing dependencies from a lerna managed package. I also think you should make it more clear in your docs that we are not meant to be using npm in managed packages. I had no idea.Anyway, as a work around for anyone else experiencing this issue:
You need to temporarily change the sibling references in
package.json
to use the local path feature. So given the dependency example I gave above:Change module-a
package.json
(The one you want to uninstall a dependency on)From:
To:
Then run the local npm uninstall. After which you must change it back otherwise lerna will hang.
@kamleshchandnani Well, there is a “help wanted” tag on this issue. I don’t have many spare cycles these days, so we’re at the mercy of folks pitching in to help implement these commands.