I’m on Mac, but the situation is similar. Yarn v2+ typically installs a local (compressed) copy of itself in the project. I believe you can use a global install, but I’ve not seen it used in practice. The global Yarn is still the Yarn v1, but if your working directory is a Yarn v2 project it simply delegates to that. (In yarn-plugin-nixify, I do some magic to skip the global Yarn v1 with a shell alias.)
The idea is that the package manager itself becomes a pinned dependency of the project. You can optionally go all the way for a ‘zero-install’ setup where you also include all dependency code in VCS, and a clean checkout may be enough to start working from right away. (No install step, hence ‘zero-install’.)
You mention building packages separately. There’s an extra difficulty here in that a package can have peer dependencies, which change the dependency tree depending on what the parent does. Normally, if your tree mentions the same package version twice, it can be shared, but peer dependencies interfere with this. Yarn v2 creates ‘virtual’ entries in the tree for this, and may do a build twice if necessary. (In yarn-plugin-nixify, you can opt-in to isolated builds, which breaks this rule and builds the dependency once, without any peer dependency context.)
So Yarn is accomplishing determinism in language package management in a different way than Nix. I’m not sure if goals align; Yarn has more a focus on package management for projects than OSes. I don’t yet really see how we’d use it in Nixpkgs, for example. Could be possible, but it’d require more thought and work, (but then again, projects like node2nix are no small effort either.)
I personally use yarn-plugin-nixify for building projects that are already flakes. I also use it in my nix-darwin config as part of a single build that installs all my CLI tools. I recently added a
installNixBinariesForDependencies option for that, which means you can create an empty project with dependencies just to get a nix build that provides the binaries for those dependencies in
$out/bin. Works well enough for me.