We use an entire TypeScript-driven stack at my company (back-end, front-end web, mobile). While creating our ecosystem, we have created a number of private Node packages in order to share as much code as possible. We also use a number of similar dev dependencies across all projects, namely:
One of the main struggles is keeping the versions for these dev dependencies in sync across all projects in order to keep the coding experience consistent across all repos. In the past we tried 2 ways:
I was hoping to create one shared private package with all of the necessary tools and their respective dependencies (Let's call it the Tools
package). The idea was to put all of the needed tools in the dependencies
section of the Tools
package, and then import only the Tools
package in the devDependencies
section of all the other repos (for example repo A
). Then, whenever I needed to update a tool, I could do all the updates in my Tools
package, publish a new version, and in turn update the Tools
package on repo A
. That way every Node project depended on the one Tool
dependency instead of 5/6.
Unfortunately, I haven't found a way to do this smoothly. So far I have tried adding the tools in the dependencies
section of Tools
, pinning a specific version of Prettier, ESLint, etc. However, when I add Tools
as a devDependency
on A
, npm seems to simply look for the most hassle-free common version and install that at the root level of A
's node_modules
folder instead of taking the version that would be most compatible across all packages. For example:
A
's devDependencies
Tools
devDependency
to ESLint and added the Tools
devDependency
on A
, and ran npm install
A
. However, it kept v8.57.0 top level and installed v9.0.0 nested under the Tools
subfolder.eslint
top level in A
, it was pointing to the wrong version.I could fix this by simply deleting the node_modules
folder and the package-lock.json
file on A
and doing a clean reinstall, but having to delete it every time means that I can no longer use Dependabot PRs as it won't do that for me, and I also will never have an assurance that the right version is installed top level without checking the node_modules
directory structure to see what is top level and what is nested.
Any recommendations on how to approach this would be greatly appreciated. While I would prefer to use private packages to be able to version correctly, any sort of solution to a similar problem would be great to hear.
npm-dedupe seems to fit the bill for my use case. Running this after npm install
will look for any possible deduplications in order to simplify the modules dependency tree. In my use case, running npm dedupe
hoists eslint v9.0.0 to the root node_modules
folder and removes it from the Tools
subfolder, resulting in what I was expecting. There is no guarantee that the tree will look as I expect it to be (for example if there are conflicting versions of eslint, then it will still nest eslint v9.0.0 in Tools
) but because a tool like eslint
would never be directly depended on I can live with that risk.
Note: According to the docs, the same result can be achieved by running npm install --prefer-dedupe
, but this was not the case for me. Running this command still kept the older version of eslint top level. It's only after running npm dedupe
that the dependency tree was corrected.