my-lib will no longer be able to resolve third-party-lib under this tree and webpack will complain when bundling.

symlink

Node has a --preserve-symlinks option, so that at runtime it treats my-lib as a subfolder of my-app/node_modules rather than it’s actual file path, though in the commit message this feature is listed as being a temporary solution:

This should be considered to be a temporary solution until we figure out how to solve the symlinked peer dependency problem in a more general way that does not break everything else

If you run node using the --preserve-symlinks flag (or webpack with resolve.symlinks set to false) then the file tree instead looks like this:

If you don’t install devDependencies in my-lib under this tree then third-party-lib will be correctly resolved, but you get the same duplication issue when devDependencies are installed. Running npm dedupe before building seems to be a possible solution for this, but unfortunately it does not process linked modules. In addition, you may not want to remove the linked package’s devDependencies if you want to develop both packages at the same time.

So, although preserve-symlinks seems to have been created to resolve issues like this, it isn’t foolproof for this scenario so and we need to find a different solution.

Lerna

Lerna resolves this with hoisting, but this solution is specific to a monorepo.

Webpack solution

The solution I’m using for webpack, for non monorepos, consists of 2 steps:

in the webpack config for my-app, add webpack aliases for known duplicated packages so that they always resolve to the my-app node_modules folder.

Duplicate Package Checker

I feel that just adding webpack aliases manually is a bit hacky as if more dependencies are added in future then they could easily be duplicated in the build without the developer realising. To manage this, we can add a check in the webpack build to ensure there are no duplicate packages.