-
Notifications
You must be signed in to change notification settings - Fork 686
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
How peerDependencies affect package versions #502
Comments
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. |
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. |
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:
|
Dependencies are transparent, and aren鈥檛. Peer dependencies hoist, and are. |
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. |
@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
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. |
@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. |
Situation 4: upgrading peerDependencies minor versionIn a situation where a peerDependency's version is bumped to its next minor version: package.json {
"name": "redux-form",
"version": "8.2.6",
"peerDependencies": {
- "react": "^16.4.0",
+ "react": "^16.8.0",
}
} So we can increase If user is accepting new minor versions automatically, both libraries should update. There is only the case when user has What are your thoughts on this? |
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, It's a breaking change because consumers of |
@theetrain Thanks for explanation! |
You could look into writing a plugin for |
@theetrain, unless you have further questions, please close this issue at your earliest possible convenience. |
Thanks everyone for your insights. I learned a lot from this. |
This major release is because the webidl2 peerDependency was bumped: #181 See semver/semver#502 for precedent.
This major release is because the webidl2 peerDependency was bumped: #181 See semver/semver#502 for precedent.
This major release is because the webidl2 peerDependency was bumped: #181 See semver/semver#502 for precedent.
This major release is because the webidl2 peerDependency was bumped: #181 See semver/semver#502 for precedent.
In my own words, unlike Situation 1: upgrading peerDependencies{
"name": "@tds/core-strong",
"version": "1.0.5",
"peerDependencies": {
- "react": ">=15",
+ "react": "^16.7.0",
"react-dom": ">=15"
}
} This does not simply mean "I refactored part of my package" like when we update It also applies even if only the minor version of {
"name": "redux-form",
"version": "8.2.6",
"peerDependencies": {
- "react": "^16.4.0",
+ "react": "^16.8.0",
}
} Situation 2: adding peerDependencies{
"name": "@tds/core-strong",
"version": "1.0.5",
"peerDependencies": {
+ "styled-components": "^4.1.3",
"react": "^16.7.0",
"react-dom": ">=15"
}
} This means "this package now requires styled-components to function, and no longer work where style-components is absent". Situation 3: removing peerDependencies{
"name": "@tds/core-strong",
"version": "1.0.5",
"peerDependencies": {
- "styled-components": "^4.1.3",
"react": "^16.7.0",
"react-dom": ">=15"
}
} 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 {
"name": "redux-form",
"version": "8.2.6",
"peerDependencies": {
- "react": "^16.8.0",
+ "react": "^16.8.0 || ^17.0.0",
}
} |
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
peerDependencies
change.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
react
that 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
{ "name": "@tds/core-strong", "version": "1.0.5", "peerDependencies": { + "styled-components": "^4.1.3", "react": "^16.7.0", "react-dom": ">=15" } }
The host application could potentially have a version of
styled-components
that is lower than 4.1.3, or the host application may not havestyled-components
installed 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-components
in particular, it may not work out of the box without necessary configurations towebpack
andbabel
.Situation 3: removing peerDependencies
In a situation where a peerDependency is removed from a package:
package.json
{ "name": "@tds/core-strong", "version": "1.0.5", "peerDependencies": { - "styled-components": "^4.1.3", "react": "^16.7.0", "react-dom": ">=15" } }
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
)The text was updated successfully, but these errors were encountered: