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)

Most upvoted comments

@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#L161

do 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?