From 850f116a60ed3b2300a537177dc480fedce22975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20W=C3=B3dkiewicz?= Date: Tue, 24 Sep 2024 12:11:32 +0200 Subject: [PATCH 1/3] test(nm): peer deps not having higher precedence when hoisting --- packages/yarnpkg-nm/tests/hoist.test.ts | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/packages/yarnpkg-nm/tests/hoist.test.ts b/packages/yarnpkg-nm/tests/hoist.test.ts index 01085d4680c..2c15dea9c6d 100644 --- a/packages/yarnpkg-nm/tests/hoist.test.ts +++ b/packages/yarnpkg-nm/tests/hoist.test.ts @@ -265,6 +265,43 @@ describe(`hoist`, () => { expect(getTreeHeight(hoist(toTree(tree), {check: true}))).toEqual(3); }); + it(`should honor package popularity considering number of all references over number of references by peers`, () => { + // . -> A -> Z@X + // -> B -> Z@X + // -> C -> Z@X + // -> D -> Z@Y + // -> U -> Z@Y + // should be hoisted to: + // . -> A + // -> B + // -> C + // -> D -> U + // -> Z@Y + // -> Z@X + const tree = toTree({ + '.': {dependencies: [`A`, `B`, `C`, `D`]}, + A: {dependencies: [`Z@X`]}, + B: {dependencies: [`Z@X`]}, + C: {dependencies: [`Z@X`]}, + D: {dependencies: [`Z@Y`, `U`]}, + U: {dependencies: [`Z@Y`], peerNames: [`Z`]}, + }); + const result = hoist(tree, {check: true}); + expect(getTreeHeight(result)).toEqual(3); + + const topLevelDeps = [...result.dependencies]; + const hoistedZ = topLevelDeps.find(x => x.name === `Z`)!; + expect(hoistedZ.references).toContain(`X`); + expect(hoistedZ.references).not.toContain(`Y`); + + const D = topLevelDeps.find(x => x.name === `D`)!; + const dDeps = [...D.dependencies]; + expect(dDeps.length).toEqual(2); + const nestedZ = dDeps.find(x => x.name === `Z`)!; + expect(nestedZ.references).not.toContain(`X`); + expect(nestedZ.references).toContain(`Y`); + }); + it(`should hoist dependencies after hoisting peer dep`, () => { // . -> A -> B --> D@X // -> D@X From af874a58077264623805b7b3e6fc947607485e3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20W=C3=B3dkiewicz?= Date: Tue, 24 Sep 2024 11:37:08 +0200 Subject: [PATCH 2/3] fix(nm): sum peer and direct usages when calculating hoisting preferences Until now the peerDependencies had a higher preference that could lead to unoptimal hoisting behaviour. Thanks to @larixer for pointing out to this particular snippet. Co-Authored-By: Victor Vlasenko --- packages/yarnpkg-nm/sources/hoist.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/yarnpkg-nm/sources/hoist.ts b/packages/yarnpkg-nm/sources/hoist.ts index 014ef1dcf92..556eb04e6b1 100644 --- a/packages/yarnpkg-nm/sources/hoist.ts +++ b/packages/yarnpkg-nm/sources/hoist.ts @@ -298,10 +298,10 @@ const getHoistIdentMap = (rootNode: HoisterWorkTree, preferenceMap: PreferenceMa const entry2 = preferenceMap.get(key2)!; if (entry2.hoistPriority !== entry1.hoistPriority) { return entry2.hoistPriority - entry1.hoistPriority; - } else if (entry2.peerDependents.size !== entry1.peerDependents.size) { - return entry2.peerDependents.size - entry1.peerDependents.size; } else { - return entry2.dependents.size - entry1.dependents.size; + const entry1Usages = entry1.dependents.size + entry1.peerDependents.size; + const entry2Usages = entry2.dependents.size + entry2.peerDependents.size; + return entry2Usages - entry1Usages; } }); From cf2ec953fbcca44758b8bd1989a72f991aea26e5 Mon Sep 17 00:00:00 2001 From: Victor Vlasenko Date: Tue, 24 Sep 2024 13:57:05 +0300 Subject: [PATCH 3/3] Marks packages for release add changelog entry --- .yarn/versions/a6283714.yml | 25 +++++++++++++++++++++++++ CHANGELOG.md | 1 + 2 files changed, 26 insertions(+) create mode 100644 .yarn/versions/a6283714.yml diff --git a/.yarn/versions/a6283714.yml b/.yarn/versions/a6283714.yml new file mode 100644 index 00000000000..357b83b3d97 --- /dev/null +++ b/.yarn/versions/a6283714.yml @@ -0,0 +1,25 @@ +releases: + "@yarnpkg/cli": patch + "@yarnpkg/nm": patch + "@yarnpkg/plugin-nm": patch + "@yarnpkg/pnpify": patch + +declined: + - "@yarnpkg/plugin-compat" + - "@yarnpkg/plugin-constraints" + - "@yarnpkg/plugin-dlx" + - "@yarnpkg/plugin-essentials" + - "@yarnpkg/plugin-init" + - "@yarnpkg/plugin-interactive-tools" + - "@yarnpkg/plugin-npm-cli" + - "@yarnpkg/plugin-pack" + - "@yarnpkg/plugin-patch" + - "@yarnpkg/plugin-pnp" + - "@yarnpkg/plugin-pnpm" + - "@yarnpkg/plugin-stage" + - "@yarnpkg/plugin-typescript" + - "@yarnpkg/plugin-version" + - "@yarnpkg/plugin-workspace-tools" + - "@yarnpkg/builder" + - "@yarnpkg/core" + - "@yarnpkg/doctor" diff --git a/CHANGELOG.md b/CHANGELOG.md index 03f75364ca8..3e96b54ffe1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Features in `master` can be tried out by running `yarn set version from sources` - `node-modules` linker now honors user-defined symlinks for `/node_modules` directories - `node-modules` linker supports hoisting into inner workspaces that are parents of other workspaces - `node-modules` linker attemps to hoist tree more exhaustivel until nothing can be hoisted +- `node-modules` linker uses aggregated count of peer and regular usages to decide hoisting priority, instead of preferring peer usages over regular as before, which should result in fewer duplicates ## 4.1.0