mirror of
https://github.com/semver/semver.git
synced 2026-07-10 19:50:47 -05:00
[GH-ISSUE #502] How peerDependencies affect package versions #5488
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @theetrain on GitHub (Feb 22, 2019).
Original GitHub issue: https://github.com/semver/semver/issues/502
Hello 👋
I'm a big fan of semantic versioning, and use it daily as I maintain the TELUS Design System. If you're curious about how we use semver with visual components, see the TDS FAQ. Forgive me as I'm going to be using npm packages in my examples as I'm unsure how to frame this in generic terms.
As a maintainer of individually-versioned React components, I would like to have guidance on how to version packages as their
peerDependencieschange.Situation 1: upgrading peerDependencies
In a situation where a peerDependency's version is bumped to its next major version:
package.json
The host application could potentially have a version of
reactthat is lower than16.7.0. Would that mean this package should release as a breaking change? (1.0.5->2.0.0)In my opinion, the package would need to have a breaking change since the host application may be forced to upgrade a pre-existing package to a breaking change, potentially requiring a refactor.
Situation 2: adding peerDependencies
In a situation where a peerDependency is added to a package:
package.json
The host application could potentially have a version of
styled-componentsthat is lower than 4.1.3, or the host application may not havestyled-componentsinstalled already. Would that mean this package should release as a breaking change? (1.0.5->2.0.0)In my opinion, the package would need to have a breaking change since the host application may be forced to upgrade a pre-existing dependency to a breaking version. Or, when adding the package
styled-componentsin particular, it may not work out of the box without necessary configurations towebpackandbabel.Situation 3: removing peerDependencies
In a situation where a peerDependency is removed from a package:
package.json
The host application would not need to be refactored in the absence of an unused package. Would that mean there is no need for deprecation notices and the package should release a patch? (
1.0.5->1.0.6)@FichteFoll commented on GitHub (Feb 22, 2019):
I don't know how peerDependencies are handled in npm, however in this case I would argue that in a world where all dependencies are properly specified, the package manager would find a conflict when the requirement of a newly added peerDependency does not overlap with the requirement of another library/dependency and thus reject the update.
In that sense, the update is so breaking that it cannot even be installed. The problem is that this is a very inconvenient situation and not covered at all by semver since it is only concerned about the API that a dependency itself defines/exposes, not in terms of what other environment contracts need to be fulfilled.
I suppose in a packaging sense, this situation is comparable to a situation where you drop support for an OS (entirely or just a specific version) where you would need to increase major because of breakage with users on that OS. Unless you never supported that OS in the first place, in which case the user relied on an implementation detail. Considering you need to specify a peerDependency explicitly, I don't think the undocumented case applies here.
Thus, as unfortunate as it sounds, I believe this to be a breaking change (by the tooling) that potentially (albeit unlikely) requires human intervention before it an be adopted.
Note that this only applies if you need a new major version of a dependency because all other sibling dependencies should accept version updates in the same major release family.
@FichteFoll commented on GitHub (Feb 22, 2019):
Related: https://github.com/semver/semver/issues/444, https://github.com/semver/semver/issues/337, https://github.com/semver/semver/issues/341
@ljharb commented on GitHub (Feb 22, 2019):
In an npm module, any peer dep change that removes a previously valid version from being valid is a major/breaking change. Peer deps are part of the public API.
@segiddins commented on GitHub (Feb 23, 2019):
I think this question basically boils down to: "are your set of dependencies part of your API?"
There are a couple of situations that raise this question:
@ljharb commented on GitHub (Feb 23, 2019):
Dependencies are transparent, and aren’t. Peer dependencies hoist, and are.
@jwdonahue commented on GitHub (Mar 13, 2019):
When it comes to packages, the manifest is an integral part of your "API". Introduce a breaking change without bumping the major version, you'll garner the wrath of your customers and possibly loose credibility. Do that too many times, and folks will start treating your minor/patch changes as-if they are breaking changes. That could be disaster for you in the case where you must get a security fix out immediately.
Just consider what it is you are putting that version number on and how it affects your customers. Except in the case of a single, stand-alone, dependency-free API; any API(s) that you ship in a package should be versioned separately from the package that contains them. If I pull your latest package and it's only had minor/patch level revision bumps, it better not break my build or product, or I will not be happy. Do that twice, I will complain loudly. By the third time, I will be dropping your product and complaining on every relevant forum I can find.
@invalidred commented on GitHub (Mar 25, 2019):
@theetrain suggestion of bumping package's major version when peerDependency's major version is bumped or when a new peerDependency is added, makes sense but it does have one tiny caveat. Looking at long term view of packages say in
tds-coreortds-communitywhich have mono repo's with independently versioned packages. There is a high possibility of having components with variable major versions which will make development slightly awkward. For instance we will have following package versions:This will be bit challenging looking a the change-logs why major versions are way off. Also it would be nice to enforce @theetrain suggestion through some build tool that ensure that packages are bumped when peer-dependencies are added or have major version bumps to avoid versioning confusion.
@jwdonahue commented on GitHub (Mar 31, 2019):
@invalidred, why would the specific values of the nodes in the dependency graph be "challenging"? The package has it's own version that may in fact be part of a larger graph. There's nothing in-congruent with having a P.1.0.0 that has dozens of dependencies in the range of (Xmin.Ymin.Zmin, XVeryLarge.YVeryLarge.ZVeryLarge). When that package is born, it must contain references to it's dependencies at whatever point they are in their life-cycle.
@unrevised6419 commented on GitHub (Nov 29, 2019):
Situation 4: upgrading peerDependencies minor version
In a situation where a peerDependency's version is bumped to its next minor version:
package.json
So we can increase
reactminor version, and releaseredux-formusing minor version.If user is accepting new minor versions automatically, both libraries should update.
If is not accepting automatic minor version, then both libraries should not update
There is only the case when user has
reactinstalled as a fixed versions.What are your thoughts on this?
Thanks!
ref: https://github.com/redux-form/redux-form/issues/4317
@theetrain commented on GitHub (Nov 29, 2019):
Hi @iamandrewluca, from what I've learned, anytime you upgrade a peerDependency from any version, you would have to release a major version to the parent module.
In your example,
redux-formhas a peerDependency ofreactthat upgrades from^16.4.0 -> ^16.8.0. Since that changes the public API for consumers ofredux-form, that would be a breaking change.redux-formwould then need to bump as such:8.2.6 -> 9.0.0.It's a breaking change because consumers of
redux-formthat are usingreact@16.4.0may not have enough functionality in order for the newestredux-formto work, potentially causing errors.@unrevised6419 commented on GitHub (Nov 29, 2019):
@theetrain Thanks for explanation!
@jedwards1211 commented on GitHub (Nov 29, 2019):
@invalidred
You could look into writing a plugin for
semantic-release, the automated package publishing tool@jwdonahue commented on GitHub (Jan 15, 2020):
@theetrain, unless you have further questions, please close this issue at your earliest possible convenience.
@theetrain commented on GitHub (Jan 15, 2020):
Thanks everyone for your insights. I learned a lot from this.
@SevenOutman commented on GitHub (Oct 23, 2023):
In my own words, unlike
dependencieslive as "implementation details" of a package,peerDependenciesare "system requirements", just like whether a sofeware runs on Windows 10 or Windows XP. It turned out easier for me to examine the impact level with this in mind.Situation 1: upgrading peerDependencies
This does not simply mean "I refactored part of my package" like when we update
dependencies, but "this package now requires react ^16.7.0 to function, and no longer work with react >= 15 < 16.7.0". And that is clearly a breaking change now.It also applies even if only the minor version of
peerDependenciesis upgraded (situation 4), which means "this package no longer work with react >= 16.4.0 < 16.8.0"Situation 2: adding peerDependencies
This means "this package now requires styled-components to function, and no longer work where style-components is absent".
Situation 3: removing peerDependencies
This means "this package now works even if style-components is absent, which used to be impossible". It's a feature enlargement, and I think it should result in a minor version bump, just like when we add new APIs.
And I believe it also applies when
peerDependenciesversion range is enlarged.@xuhdev commented on GitHub (Jul 8, 2024):
I've also written an article on this:
@ljharb commented on GitHub (Jul 8, 2024):
@xuhdev in npm, adding an optional dependency is semver-major as well, because someone could have a conflicting version already installed; additionally, bumping the minor or patch of a peer dep is also always a semver-major change.
@unrevised6419 commented on GitHub (Jul 8, 2024):
@ljharb, the argument they gave in favor of peer dependencies being a minor/patch is that the user, in the cause, can update those packages that theoretically are back compatible. The only exception when for the user in cause somehow those minor/patch updates may break something.
PS: also, the latest npm version should protect us from conflicting dependencies.
@ljharb commented on GitHub (Jul 8, 2024):
@iamandrewluca the user can update anything with any breaking change - it's a breaking change if they have to do anything besides update your package. That includes all behavior of all versions of npm, including the latest one.