The way I see it, the "dependencies" hash in package.json right now is
pulling double-duty. In some cases (where the value of a dependencies field
is a semver), it's there to describe *generally* what module versions it
expects to be compatible with. In other cases (when the value of a field is
a URL), it's there to describe the *exact* version of a module it's used
with.
This mixed-purpose approach has a few shortcomings: for one, packages
outside the canonical registry can't specify version ranges. What's worse,
any discussion of these shortcomings inevitably devolves into a
back-and-forth over the utility of the registry (with arguments over
everything from naming techniques, to implied triviality, to diplomatic
protocol).
Putting that aside for the moment, I modestly propose we split these duties
into two hashes:
- Make it so the "dependencies" (and "devDependencies") hash is always
shrinkwrapped. This keeps the same read semantics "dependencies" always
had, so nothing breaks (that wasn't already broken).
- Use a different hash (let's call it "wants") that handles
future-looking package usage, where each package (by
node_modules/package.json/require() name) has a hash for a value, that
includes its location (npm registry, github repo, HTTP tarball, etc), its
acceptable semver range (for (couch and git) servers that can list
available versions), peer requirements, and any new package use factors
that may arise in the future (much as how the other hashes in package.json
are flexible, like "scripts" and the root hash itself).
Loose semver ranges used to be a Big Important Deal, back in the packaging
flatlands of Python and Ruby. In those worlds, every module in use had to
agree to share one particular version of any module- every module had to
accommodate any potentially outdated code. Where a dependency was coming
from didn't matter, but the ways it would be acceptable to come was.
In Node, however, packages, once installed, will never see their
dependencies versions any older than the latest they were written (unless
they're peerDependencies). The one purpose of ranges is to allow potential
optimizations and bugfixes from any future revisions of dependencies,
without having to explicitly declare it. At this point, keeping that
looseness, as a core attribute of the runtime, is a weakness, one that's
overshadowing the increasingly pressing issue of where that package is
located.
Here are the gains yielded by splitting these purposes:
- "dependencies" is tightened up for repository packages (bringing them
to the specificity non-repository packages are already subject to). New
packages can't rely on ranges that can become invalid (due to either a
too-loose semver requirement or a breaking change in a minor version). A
guaranteed shrinkwrapped dependencies field means you know *exactly* what
revisions the package was developed against at time of publication.
- Packages outside the registry are no longer second-class citizens.
Notably, using them no longer blocks you from specifying a compatible range
of versions to update to.
- Letting packages specify metadata beyond location allows specific
installation profiles like "devDependencies" to be specified by
black/whitelist, eg. {"exclude":"prod"} or {"include":["doc","build"]}.
These would be transitional changes necessary to NPM:
- Calling "npm install" or "npm update" with a package.json that uses
semver ranges (or tagless git URLs) automatically shrinkwraps
"dependencies" and converts the existing "dependencies" values to the
equivalent "wants".
Here's what would have to change expectations to accommodate this:
- `npm update` would have to read the "wants" field, and would need
additions to find available semver tags in non-registry locations (like
tags in a Git repo).
- For developers, the listed semvers would need to be loosened/tightened
appropriately, and `npm update` would be required to update a code's
dependencies. (Good.)
The only things that expect the behavior of `npm install` to incorporate
inherent updates would just need an explicit `npm update` step.
What does the community think? If npm wouldn't be willing to go ahead with
something like this, any interest in producing some kind of fork?
--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines:
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
---
You received this message because you are subscribed to the Google Groups
"nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.