Open octogonz opened 2 years ago
This sounds useful, and is definitely more clear behavior.
After some further investigation, using root package.json isn't quite right since it can lead to some complexity regarding satisfying peer dependencies of the hoisted packages. A better option would be to use the afterAllResolved
pnpmfile hook to select from existing installed dependencies which ones should be hoisted in the .
importer.
Summary
Problem: In Rush Hour East - Sep 2022 we discussed a problem report where a project failed to build after a partial/filtered install (
rush install --to example-project
), but the same project built correctly after a full install (rush install
).The cause was PNPM hoisting of indirect dependencies: With PNPM's default configuration (
hoist-pattern: *
), the hoisted set includes a version of every package, and any of these is potentially importable by a poorly behaved package. However PNPM partial install only hoists its own dependency tree (presumably because the full*
is too many packages, which would undermine the savings of a partial install).Solution: The ideal solution would be to disable hoisting entirely (the Rush Stack monorepo accomplished this in PR #3474). However eliminating hosting is challenging for most large monorepos, because many legacy NPM packages have lots of phantom dependencies, and determining the exact
.pnpmfile.cjs
fixes can be timeconsuming compared to hoisting.@dmichon-msft proposed an intermediary solution:
hoist-pattern: *
in .npmrc)rush install
should add these NPM packages to the"dependencies"
field of the generatedcommon/temp/package.json
fileCompared to hoisting, the benefit is that version ranges can be specified explicitly, rather than relying on PNPM's heuristic.
This algorithm is similar to the old preferred versions behavior (with
useWorkspaces=false
).CC @iclanton @chengcyber @elliot-nelson