yarnpkg / berry

📦🐈 Active development trunk for Yarn ⚒
https://yarnpkg.com
BSD 2-Clause "Simplified" License
7.4k stars 1.11k forks source link

[Feature] Support `yarn dedupe --strategy fewer` #2297

Open ocavue opened 3 years ago

ocavue commented 3 years ago

Describe the user story

I have a project which uses next and next-offline as dependencies. The package.json of these two packages are as below:

// next/package.json
{ "dependencies": { "webpack": "4.44.1" } }
// next-offline/package.json
{ "peerDependencies": { "webpack": "^4.19.1" } } 

next-offline has webpack in its peerDependencies, so I have to also add webpack into my project's package.json to avoid the warning from Yarn. Since I don't actually use webpack directly and I don't care which version of webpack I'm using, I simply write "webpack": "^4" in package.json

// my-project/package.json
{ 
  "dependencies": {
    "next": "^10.0.4",
    "next-offline": "^5.0.3",
    "webpack": "^4"
  }
}

The latest webpack@^4 version today is 4.44.2, which cause Yarn to install two version of webpack in my-project:

# my-project/yarn.lock
"webpack@npm:4.44.1":
  version: 4.44.1

"webpack@npm:^4":
  version: 4.44.2

Install two versions of the same package (not specifically webpack) could cause some issues.

Describe the solution you'd like

Implement yarn dedupe --strategy fewer. This command should update the yarn.lock above to:

# my-project/yarn.lock
"webpack@npm:^4, webpack@npm:4.44.1":
  version: 4.44.1

I'm using renovate to manage my dependencies, which can run npm dedupe or yarn dedupe after every update (docs). This means that I don't have to run yarn dedupe myself so this is an acceptable solution for me.

Describe the drawbacks of your solution

Please let me quota the document from yarn-deduplicate --strategy fewer:

Note that this may cause some packages to be downgraded. Be sure to check the changelogs between all versions and understand the consequences of that downgrade. If unsure, don't use this strategy.

Describe alternatives you've considered

There is a RFC to fix this kind of issue at https://github.com/yarnpkg/berry/issues/1001 (which has an almost identical example). However, it seems that this PRC hasn't been implemented.

why not make it a plugin

Because we already have yarn dedupe --strategy highest.

aaronadamsCA commented 2 years ago

I would use this feature.

We use Renovate to pin every package to an exact version so we can test every upgrade. Sometimes a transitive dependency will cause a newer version to be added to the lock file as well. These duplicate dependencies are a common cause of broken tests/builds.

I expect yarn dedupe --strategy fewer would hold back the newer transitive dependency versions until we upgraded ours.

We are currently using resolutions as a workaround; for example we define resolutions: { "webpack": "5.72.1" }, and Renovate keeps this in lockstep with our individual packages' Webpack versions, ensuring we only ever get one version of Webpack. Of course this isn't much fun to maintain, and can't be used in every case.

christophehurpeau commented 1 year ago

Hi, if anyone is interested I forked yarn-deduplicate and made it work with yarn berry. (npm here: https://www.npmjs.com/package/yarn-berry-deduplicate)

Usage:

yarn dlx yarn-berry-deduplicate

Default strategy is fewerHighest (similar to running fewer then highest strategies with yarn-deduplicate) as highest did not make sense because it works out of the box with yarn berry. The best would be an implementation in yarn, but deduping can solve issues so this temporary solution could help !