Closed saltire closed 2 years ago
I experienced this bug on Windows, NPM version 6.14.11. npm update
failed to update package.json but a targeted install worked.
Interestingly, it seemed my global packages were also messed up around the same time this started. For instance, npm list -g --depth=0
would show the global packages but some of them would have messed up versions such as snyk@0
. npm outdated
would insist the package was outdated even after updating. Re-installing the packages or npm didn't fix.
I was able to fix this by completely uninstalling node, npm, Windows build tools, and chocolatey. I deleted all the related folders in my user folder, programs folder, %appdata%, %localappdata%, and %programdata%. A simple node/npm update wouldn't fix it, so something was messed up in one of those folders. After re-install of node/npm, package.json was updating as expected and the global packages issue was resolved.
Same bug on windows 10 node v12.16.0 After npm upgrade versions in package.json not automatically updated
@saltire sorry for the confusion, we need to update the docs to clarify that npm update
will install & update the package-lock.json
but not modify the spec defined in package.json
; As you noted, you can still update that by running npm install <pkg>@<version>
- this was a breaking change from v6, as that previously would modify package.json
@saltire sorry for the confusion, we need to update the docs to clarify that
npm update
will install & update thepackage-lock.json
but not modify the spec defined inpackage.json
; As you noted, you can still update that by runningnpm install <pkg>@<version>
- this was a breaking change from v6, as that previously would modifypackage.json
And what command can I use to update all packages, modifying specs in package.json?
@saltire sorry for the confusion, we need to update the docs to clarify that
npm update
will install & update thepackage-lock.json
but not modify the spec defined inpackage.json
; As you noted, you can still update that by runningnpm install <pkg>@<version>
- this was a breaking change from v6, as that previously would modifypackage.json
There should be a better way than running npm install <pkg>@<version>
on each package to update package.json. Maybe it is also time to introduce wildcards (or regular expression as in ncu), especially with scopes as in npm update @babel/*@7
Since what I want to do is update the versions listed in package.json to the latest "Wanted" version and not the "Latest" version (as shown by npm outdated
), this becomes a laborious process and for now I think I'm probably better off staying on npm v6 or downgrading to npm v6 (if using node v14).
I have my package versions set to "want" the latest non-breaking changes if semver is respected. I use the version in the package.json to help me know the version I actually last got and tested locally. When a non-breaking change actually breaks something, I update package.json to lock the previous version, report the issue and track the package for a fix.
I'm also wondering what the rationale for the breaking change was. There was already an option --no-save
if you didn't want your package.json
modified. Now there is no way to get the v6 behavior, other than one by one installing the latest specific wanted version of each package.
I was extremely surprised when npm up
command didn't update package.json file. I really hoped that it was a cli bug but @darcyclarke upset me :(
@saltire sorry for the confusion, we need to update the docs to clarify that
npm update
will install & update thepackage-lock.json
but not modify the spec defined inpackage.json
; As you noted, you can still update that by runningnpm install <pkg>@<version>
- this was a breaking change from v6, as that previously would modifypackage.json
Still not sure how to update all packages and change package.json
Several people recommended me npm package for dependencies updates. Maybe it will be useful for somebody.
Using a package to update packages is so weird. This is not the way it should be. By the way is there a way for the package to do "exactly" what npm update was doing before?
Using a package to update packages is so weird. This is not the way it should be. By the way is there a way for the package to do "exactly" what npm update was doing before?
You can write your own script something like this
scripts/up.js
const {execSync} = require('child_process')
const packageName = process.argv[2]
const outdatedInfo = JSON.parse(execSync(`npm outdated -l --json ${packageName}`))
const packageCurrentVersion = outdatedInfo[packageName].current
const packageWantedVersion = outdatedInfo[packageName].wanted
const packageType = outdatedInfo[packageName].type
const isDev = packageType === 'devDependencies'
const updateInfo = execSync(`npm i ${isDev ? '-D' : ''} ${packageName}@${packageWantedVersion}`)
console.log(updateInfo.toString())
And then use node ./scripts/up webpack
I know it's not a good solution but why not?
@srknzl npm
is a package. It's really not weird.
I mean why other 3rd party package if DeFacto standard is npm package
@saltire sorry for the confusion, we need to update the docs to clarify that
npm update
will install & update thepackage-lock.json
but not modify the spec defined inpackage.json
; As you noted, you can still update that by runningnpm install <pkg>@<version>
- this was a breaking change from v6, as that previously would modifypackage.json
This, is a serious breaking change / issue when migrating to v7, and this is not documented anywhere at this time: I just noticed that during migration.
The important questions now are:
npm@6
did before?package.json
file with npm@7
?Thanks for taking the time to give a clear answer to the community :wink:
For now, I decided not to upgrade to npm >= 7. With this behavior, I lose track of what is happening with my project, which dependencies I am upgrading, and which still need to be upgraded (via the npm up
command). I can't rely on checking changes to the lock file as this file is not meant to be read by humans. If I may suggest at least adding a CLI option to update the spec file when updating dependencies. This way we could have the previous behavior as an opt-in.
Regards.
Stumbled upon this issue after upgrading npm, skimmed another issue thread and this one; at least two maintainers claim that this was an intentional breaking change, yet I can't find the rationale behind it (in fact, I wasn't even able to find any mention of it in the npm v7 changelogs at first glance).
I'm fine with adjusting my workflow, but at the moment I can't quite figure out how this new behavior of npm update
is better than before (as others have pointed out, seeing incorrect versions package.json
seems confusing at best to me).
@npm/cli-team please let us know, How the hell can we update all modules in package.json dependencies to their latest, from now on???
@npm/cli-team please let us know, How the hell can we update all modules in package.json dependencies to their latest, from now on???
For now I have not found any alternative to npm i -g npm-check-updates && ncu -u
. They should really implement this in npm@7.
There’s also,npx salita
NPM Version 7 feels like if some .NET lovers have sneaked into the npm development team and trying to ruin the JS development experience.
And what command can I use to update all packages, modifying specs in package.json?
@CageFox @arash-bizcover the fact is npm@6 never udpated package.json beyond the specs defined within itself. It might be controversial because it is a breaking change with npm@6, but there is little point in automatically evolving this file.
If you distributed an app, you should be distributing a shrinkwarp file. If you distributed a library, you'd only bump the specs in package.json when manually conducting a major upgrade.
See also https://github.com/npm/cli/issues/708#issuecomment-840725231 and https://github.com/npm/feedback/discussions/270
@CageFox @arash-bizcover the fact is npm@6 never updated package.json beyond the specs defined within itself. It might be controversial because it is a breaking change with npm@6, but there is little point in automatically evolving this file.
@n1ngu yes That specs defined within itself is what exactly we are using, and there is a strong point automatically update based on the package.json file.
We(as well as many others) have tons of dependencies for our applications which we are the owner of those dependencies as well. When we update some dependencies we want our applications CICD pipelines to run npm update on test environments and without manually changing each bit on each application build and test the latest dependencies when our tests and health checks pass CICD just simply runs npm i
and then automatically commit back(PR) package.json to the repository without anyone touching anything and everything gets updated and we can also see what is the latest version of our first-class dependencies easily on package.json.
We(as well as many others) have tons of dependencies for our applications which we are the owner of those dependencies as well. When we update some dependencies we want our applications CICD pipelines to run npm update on test environments and without manually changing each bit on each application build and test the latest dependencies when our tests and health checks pass CICD just simply runs
npm i
and then automatically commit back(PR) package.json to the repository without anyone touching anything and everything gets updated and we can also see what is the latest version of our first-class dependencies easily on package.json.
@arash-bizcover Since you are using the word "application" I'll insist: for that workflow you'd need to lock the dependencies in a shrinkwrap file. Then again, the package.json specs need not to evolve.
If you meant "library", you should only commit back the package-lock.json file, run your tests to check nothing broke, and let your library end-users update any transient dependency (yours or not) at the pace they want.
I've been waiting patiently for for months now for this seemingly obvious bug to be fixed only to now figure out it is as designed. When I look at package.json I expect to see the packages and versions I'm currently working with. Is that not normal? I just cannot understand the benefit of not at least offering the option of updating package.json through a flag. Especially since that is the legacy behavior.
Our whole team is stuck on npm 6 due to this bug. Npm 7 is useless for us.
@n1ngu Why is this so hard just to return back the feature we need? What you explained for us is yours way to do the things, it can not be acceptable for all, many people do the same things in another way and this bug prevents us from using npm 7 at all
I totally agree with @imarotte and @CageFox. We are in the same situation.
What is the point of having the exact, but wrong package version in package.json then? That's misleading. Why not only keep the major version if that is what matters anymore? In a perfect world where patch releases sometimes don't introduce breaking changes it could be fine, but it's never going to be that. And it could be really hard to debug problems when you are supposed to have the same package version like others but in reality not (I've been there)
@CageFox I have no stake in this. I'm just glad how npm@7 works, like all the people that will never show up in this discussion.
I just wanted to share the idea that this is not a bug. Sure, some people will have a very special workflow that relied on the old behavior. But for the bulk of people complaining here, I think the new behavior isn't really a blocker.
But if it worries you this much, read the linked feedback discussion: maintainers are open to recover the old behavior via cli flags.
@Allain55 if a dependency does not abide by semver, you should freeze it instead of using a caret version spec, and this would never let npm update
to update it anyway.
Maybe the command npm outdated shouldn't update anything by itself, just print a report table and prepared commands like:
npm update package1@wantedVersion
npm update -D package2@wantedVersion
The maintainer could then quickly review and consciously implement the updates by copy-paste.
[...] The maintainer could then quickly review and consciously implement the updates [...]
For that workflow, npm-check-updates
got you covered https://github.com/npm/cli/issues/2704#issuecomment-882393993
Bonus: it can update dependencies beyond the defined specs, which no version of npm would do.
While its not quite the same as the old behavior of npm update
in npm@6 what i normally want to do is upgrade all minor/patch versions and write to package.json, but never upgrade major versions (prefer to do those one-by-one and manually). So if you generally use versions like
"cors": "^2.8.5"
(caret for minor versions)
then
npx npm-check-updates --target minor --upgrade; npm install
will upgrade all packages to latest minor version
If you are more risk-averse and only want to upgrade patch versions and your package.json is
"cors": "~2.8.5"
(tilde for patch versions)
then
npx npm-check-updates --target minor --upgrade; npm install
will upgrade all packages to latest patch version
However this won't work if you have a mix of ^ and ~ versions
Something that would work (an alternative and a potential algorithm analogue) is, for each dependency/dev dep foo
, run npm install foo
which will respect the semver range in package.json.
How about this:
npm install `node --print 'const package = require("./package.json");Object.keys(package.dependencies).join(" ")'`
This grabs the list of dependencies, turns into a space seperated list and passes it to npm install
Include dev deps in there and you’ve got something workable.
hmm one problem with my solution above is that if you have a frozen version like
"millify": "3.5.2",
it will change it to
"millify": "^3.5.2",
which is probably NOT what you want
Here's a new version which only does npm install for the version specifiers which start with ^ or ~
npm install `node --print 'const package = require("./package.json");Object.keys(package.dependencies).filter(key=>{const char = package.dependencies[key][0]; return char=="^"||char=="~"}).join(" ")'`
That’s definitely what you want; a lockfile pins versions, and they shouldn’t be pinned in package.json.
er no, if i specify "millify": "3.5.2" (because say 3.5.3 has a bug) i do NOT want to upgrade that package automatically ever.
Then you’d use =3.5.2 to make it explicit.
i must admit ive been using npm for years and never heard of the = operator. Is there any functional difference between
"millify": "3.5.2" and "millify": "=3.5.2"
its not documented on https://docs.npmjs.com/cli/v7/configuring-npm/package-json#dependencies as far as i can see...
and yet, it’s a range.
Sorry I don't understand. How is "millify": "3.5.2" a range? Doesn't that mean 3.5.2 exactly?
No, i mean “=3.5.2” is a range - one that contains exactly one version.
Will this get addressed?
I recently updated to npm 8.3.0 and I received the "pleasant" surprise just like all of you. Since it seems that nothing has changed for more than an year, I'm really worried and I wonder if I should revert back to npm v6 or keep up with v8. If there was any hint that this behavior will be restored or at least introduced as an optional argument, I would stick to v8.
@jginsburgn @hardmaster92 Sorry but, as critical as this looks for you, could you please read the whole thread and the linked discussions before commenting that?
The team has decided that fixing usage of npm update --save
was the best way moving forwards 😊 it enables saving dependency ranges to package.json
as expected. It's also worth noticing that you can also just set save=true
in a .npmrc
file in case you want that to be the default behavior..
npm@8.3.2
is out now with the fix 🎉
It seems the issue resolved and now we can move to actual npm too
@ruyadorno Great news! Big thanks for that :tada:
.npmrc
of 2022:
global-style=true
engine-strict=true
legacy-peer-deps=true
lockfile-version=3
save=true
@sla100 legacy-peer-deps should be avoided; that's just papering over your invalid dependency graph, and since engines is purely advisory, engine-strict
is going to break just as often as it helps you. I've never heard of global-style
, and save=true
is the default.
Current Behavior:
When running
npm update
, packages are updated normally, package-lock.json is updated, but package.json is not. (npm install [package]@[version]
does update package.json as expected.)Expected Behavior:
The package.json file should be updated with the newly installed versions, as specified in the npm-update docs.
Steps To Reproduce:
npm update
Environment:
OS: Mac OS Big Sur Node: 14.15.5 NPM: 7.5.4