NPM Needs a better solution for local development
Given the following layout of multiple modules in development:
my-application depends on
If I’m making changes to both of these projects, or I wish to make changes to
my-lib and see the effect they have within
my-application, I currently have two supported options:
- Publishing tagged versions to the global repository, or
The first option works, but it is slow, requires constantly changing the tag name, consumes valuable community resources, and pollutes the global namespace if you’re not using private packages.
The second option (using a symlink) while it apparently works for most people most of the time, can produce significantly different results than what you would get by installing a “real” published dependency via the npm public repositories:
- The fileset is different, as all files located within the source tree are visible, not just those specified by
- More importantly, due to the node module resolution algorithm, the dependencies of
my-libwill be wrong:
- Concrete dependencies will be immune from npm’s resolution of version ranges and de-duplication
peer-dependencieswill be present and resolved within the scope of
The second problem can cause pretty serious difficulties, when it leads to duplicates of libraries that should not have multiple instances, such as react, and it also breaks TypeScript: Any
@types/foo dev-dependencies become effectively duplicated with different identities, causing a bunch of nonsensical
Expected a FooBarBaz, but found a FooBarBaz errors.
I’m not sure what the best solution to this problem is, but I have a proposal that might be acceptable:
- Add a flag to
npm publishwhich performs all the steps of a publish, but then copies the artefact to a known location within the local filesystem’s npm cache
- Add the ability to (within the scope of
my-application) temporarily set the resolution of an installed dependency to use the local artefact as the source instead of fetching it from the cloud or using a direct symlink as currently used by
The idea to use a known location instead of relative paths to the artefact produced by
npm pack is so that it works for transitive dependencies also, in case your project is more complex than this simple example, perhaps you have several libraries and an application which all depend on a “common” or “base” library, and they might not all have the same relative paths to it.