berry: [Bug?]: peer dependency no longer guarantees to be the exactly the same one as the one used by the ancestor
Self-service
- I’d be willing to implement a fix
Describe the bug
hi! First of all thanks for all your great work!
I found that after converting few projects to yarn workspaces the behavior of peerDependencies
has changed: it’s no longer guaranteed that used peer dependency in some workspace is exactly the same as in another workspace that consumes the 1st workspace. While docs say that they should be the same.
I’ve tried to add reproduction but messed up with filesystem somewhere. Though I assume it’s clear what behavior I expect (if not, please, let me know, I’ll do smth about it).
Would be very thankful for any advice.
The final aim: to be able to have different versions of react
in a
and b
workspaces and make pkg
workspace use exactly the same version of react
depending on which workspace (a
or b
) it’s executed.
To reproduce
const { promises: fs } = require('fs');
await fs.appendFile('.yarnrc.yml', '\nnodeLinker: node-modules\n')
// initializing workspaces
await Promise.all([fs.mkdir('a'), fs.mkdir('b'), fs.mkdir('pkg')]);
await Promise.all([
fs.writeFile('package.json', JSON.stringify({ workspaces: ['a', 'b', 'pkg'] }, null, 2)),
fs.writeFile(
'pkg/package.json',
JSON.stringify(
{
name: 'pkg',
version: '0.0.0',
peerDependencies: {
react: '>16.0.0',
},
},
null,
2,
),
),
fs.writeFile(
'a/package.json',
JSON.stringify(
{
name: 'a',
dependencies: {
pkg: '0.0.0',
react: '16.8.0',
},
},
null,
2,
),
),
fs.writeFile(
'b/package.json',
JSON.stringify(
{
name: 'b',
dependencies: {
pkg: '0.0.0',
react: '17.0.0',
},
},
null,
2,
),
),
]);
await yarn('install');
// initializing files
await Promise.all([
fs.writeFile(
'pkg/index.js',
'module.exports = { reactVersion: require("react").version }',
),
fs.writeFile(
'a/get-react-version-from-package.js',
`const fs = require('fs');
fs.writeFileSync(__dirname + "/react-version.txt", require("pkg").reactVersion)`,
),
fs.writeFile(
'b/get-react-version-from-package.js',
`const fs = require('fs');
fs.writeFileSync(__dirname + "/react-version.txt", require("pkg").reactVersion)`,
),
]);
// running the files
await Promise.all([
yarn('node', 'a/get-react-version-from-package.js'),
yarn('node', 'b/get-react-version-from-package.js'),
]);
// one of these is failing
await expect(fs.readFile('a/react-version.txt', `utf8`)).resolves.toBe('16.8.0');
await expect(fs.readFile('b/react-version.txt', `utf8`)).resolves.toBe('17.0.0');
Environment
System: OS: macOS 11.4 CPU: (16) x64 Intel® Core™ i9-9980HK CPU @ 2.40GHz Binaries: Node: 15.14.0 - /private/var/folders/bt/6t9rw3zs4gj58yc8xsp8xfbr0000gn/T/xfs-09a94538/node Yarn: 2.4.2 - /private/var/folders/bt/6t9rw3zs4gj58yc8xsp8xfbr0000gn/T/xfs-09a94538/yarn npm: 7.7.6 - ~/.nvm/versions/node/v15.14.0/bin/npm
Additional context
No response
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 16 (7 by maintainers)
@larixer sorry for being silent for a while. I guess your suggestion regarding the #3267 is not actual anymore 😦
I found out that yarn added support for pnpm linker (#3338) and pnpm added injected thing that resolves their issue (https://github.com/pnpm/pnpm/issues/3558) equivalent to this one.
But unfortunately using yarn with pnpm and
injected
under the hood is not possible atm because of https://github.com/yarnpkg/berry/blob/b292d2b9b35070fe5ecde784326c905ac7a2cfdc/packages/plugin-pnpm/sources/PnpmLinker.ts#L161do you think at some point in the future it can possible? @arcanis maybe you can advise as well
why I’m asking is because migrating to PnP or pnpm seems to be the only reliable solutions to this issue atm. If we do not consider some totally different tools like Bazel (though don’t know if it helps) or rush.js (that recommend using pnpm)
I fixed a few issues in your repro (cf the last edit I made in your post) and the repro works as expected. Yarn is certainly supposed to guarantee that peer dependency inherit the exact instance from their parents, and we have a few tests enforcing it, so this behaviour sounds surprising. Can you check whether it might be a configuration issue on your side?