tableau / npm-pack-here

An alternative to the Yarn link and NPM link workflows, this tool packs a local NPM project and puts the packed contents into the given destination directories.
MIT License
19 stars 4 forks source link

Should `useGlobalCache` be set to true by default? #11

Open greyepoxy opened 4 years ago

greyepoxy commented 4 years ago

Feature Request Overview

Should we set useGlobalCache to true by default instead of setting destinations to ./local_modules?

The Problem

Today useGlobalCache is set to false by default and the destinations option is set to the relative working directory path ./local_modules. See the documentation describing this here. This works well for single level local dependencies but when multi-level local dependencies become involved, yarn/npm treat different path locations as different versions. So if someone spends the time to setup a multi local dependent situation where they want all levels to resolve to the same local version of a dependent package, they will see multiple of that dependency.

For example, given a classic diamond dependency

If someone wanted to setup a projectD to be locally developed they might do the following

  1. In projectB run npm-pack-here --target <path-to-projectD> and the follow up yarn/npm commands a. In projectB run yarn add file:local_modules/<name-of-projectD> b. In projectB run yarn install --check-files
  2. In projectC run npm-pack-here --target <path-to-projectD> and the follow up yarn/npm commands a. In projectC run yarn add file:local_modules/<name-of-projectD> b. In projectC run yarn install --check-files
  3. In projectA run npm-pack-here --target <path-to-projectB> <path-to-projectC> and the follow up yarn/npm commands a. In projectA run yarn add file:local_modules/<name-of-projectB> file:local_modules/<name-of-projectC> b. In projectA run yarn install --check-files

At this point the expectation would be that locally in projectA both projectB and projectC depend on the same version of projectD but in reality they do not.

Instead they depend on two different versions of projectD,

The developer would have to know that they need to pass in the --useGlobalCache flag to all of the npm-pack-here commands to make this work.

Solution Idea

Make useGlobalCache the default (instead of destinations equal to [./local_modules]). Then npm-pack-here will always pack to the global cache location, which will make all multi-level dependency scenarios like the one described above just work.

For the most part this should also have little impact on existing single level dependency scenarios, as when people run npm-pack-here for the first time within some project it lists out the next step yarn commands with the path (which will now just be the global cache location).

Drawbacks to this approach are that changing the default would be a breaking change. This will in some ways make npm-pack-here much more tuned for use with yarn / npm projects. Kind of diverging from the idea that "there is some target/source", "there is a given destination", all npm-pack-here does is pack the content form the target to the destination. I wonder if we should split out the commands to make this more obvious.

Also another potential drawback, the global cache currently does not support multiple versions of a packed project within it. Its unknown currently if their are scenarios where people will desire having two (or more) versions of a local dependency all being packed and used within another set of projects. If they do, then defaulting to the global cache will introduce new issues. Will need to re-think how the global cache works for cases like that.

Alternative Ideas

In the multi-level local diamond dependency scenario described above, likely yarn resolutions (not sure if their is a npm equivalent) could be used to force resolution of the sub dependencies all to the same local version. This approach has the advantage (or possible disadvantage) that it could be likely setup from just the top level dependency (without having to locally clone all the intermediate dependencies). Either way probably want to document this approach as well.

Could also split out the existing cli command into two "pack content from this target/source location to this destination" from "pack content into this node project (with dependencies)." First command would still default to ./local_modules while the second would default to the global cache. This could be a good idea as it might provide clarity to how npm-pack-here works for different workflows.

A third idea, instead of useGlobalCache we could pack into a sub folder of the target/source project. This might be even better to packing into the global cache as it would likely avoid the drawbacks listed above (could support multiple versions of a given local project, not diverging to far from the "source" to "destination" idea). Biggest issue of doing this is that this projects name kind of becomes a little misleading.

Example

Given the diamond dependency described above

If someone wanted to setup a projectD to be locally developed they would do the following

  1. In projectB run npm-pack-here --target <path-to-projectD> and the follow up yarn/npm commands a. In projectB run yarn add file:<path-to-npm-pack-here-global-cache>/<name-of-projectD> b. In projectB run yarn install --check-files
  2. In projectC run npm-pack-here --target <path-to-projectD> and the follow up yarn/npm commands a. In projectC run yarn add file:<path-to-npm-pack-here-global-cache>/<name-of-projectD> b. In projectC run yarn install --check-files
  3. In projectA run npm-pack-here --target <path-to-projectB> <path-to-projectC> and the follow up yarn/npm commands a. In projectA run yarn add file:<path-to-npm-pack-here-global-cache>/<name-of-projectB> file:<path-to-npm-pack-here-global-cache>/<name-of-projectC> b. In projectA run yarn install --check-files

This will result in just a single version of projectD, the one in the global cache.

Teachability, Documentation, Adoption, Migration Strategy

Would need to update documentation on the default options here.