Nodejitsu

Save time managing and deploying your node.js app. Code faster with jitsu and npm

A summary of scoped modules in npm

About the author

Name
Location
Worldwide
nodejitsu nodejitsu

Summarizing the "scoped modules" discussion

Starting towards the end of this past week a discussion started on the npm repository on Github which represents big changes to how the npm client will work. This is important and we want your input! The purpose of this blog post is to try to summarize the discussion so far and make it more accessible if you haven't already been following it.

Lets start with some definitions:

  • "global" modules these are modules that follow the naming convention that exists today. You require('foo') and there is much rejoicing. They are owned by one or more people through the npm owner command.
  • "scoped" modules these are new modules that are "scoped" under an organization name that begins with an @.

In addition to introducing a new type of module this specification should allow for an easy convention for multiple registries. From the original post by Isaac Schlueter:

Each @org will map to a specific registry in the config (or the default --registry config, which defaults to registry.npmjs.org, if not specified).

We can then also scope auth info to each registry, and voila, we have multiple registry support that works, doesn't conflict with anything that already exists, doesn't result in fetching the right thing from the wrong place.

@org/pkg modules will be dropped onto the filesystem at node_modules/@org/foo, so require("@org/pkg") will work.

And since that's the actual package name, you'll do "dependencies":{"@org/pkg":"1.x"} in your package.json file.

As a way of implementation details, the @org/pkg thing will map to npm://{registry}/@org/pkg, where {registry} is the registry that is assigned to the @org or the default --registry config. npm:// urls will be fetched via https, and always send authentication information, and treat 404's as a potential "maybe you don't have permission" response.

The TL;DR here is "org ns as step towards private modules", but overall the private module mechanism, OAuth2, and package signing are not in the scope of this discussion for now.

Why the @ symbol?

Although a few different reasons were discussed but the most compelling one was suggested by Dominic Denicola, a member of the npm core team.

I like @org/package much more than org/package, independent of any backward-compat issues. The @ sign is a nice differentiator. E.g. require("@kriskowal/q") versus require("q/queue"): the former is Kris's Q package; the latter is the queue module inside the global q package.

This was rebutted by Sam Bisbee suggesting formal deprecation:

I'm +1 on deprecating global namespaces and requiring that all packages live under a top level name space. That top level name space could be used as a vendor/org, username, etc. Generally this is a requirement or best practice in other languages that have used name spacing. Strictly speaking the NPM implementation doesn't have to care whether it's a user or an organization.

This also removes the above sub-module reference problem because sub-module references would become, for example, require('kriskowal/q/queue'); Any reference to require('q/queue'); would reference the q organization/user's queue package.

"global" modules cannot depend on "scoped" modules

A major point of contention in the current discussion is whether a global module can depend on a scoped module. The intention of the main specification authors is that it is a cowpath that nudges developers in the new direction while maintaining backwards compatibility. The best summary of this point was here

I think this is a problem that will solve itself over time. It allows the current module system to remain forward-compatible, and creates a cowpath by which new modules will gradually adopt the new system. Assuming the registries and clients all enforce the rules, it requires very little else be done by developers, which makes it feel like a pretty natural evolution of the system.

Others however have suggested that by not allowing global modules to depend on scoped modules that it will stifle growth of the module ecosystem by putting up roadblocks or discouraging authors of scoped modules. For example, quoting my comment:

  1. Company X makes a module, some-thing that they intend to Open Source.
  2. Company X publishes that thing to npm as a private package @company/some-thing
  3. A year later Company X wants to release some-thing as Open Source, but the global some-thing is taken.
  4. Company X is now discouraged from Open Sourcing because of additional breaking config changes in package.json files if they change the name to some-other-thing and making the scoped @company/some-thing Open Source can't be used by global modules.

The underlying mechanism for allowing "global modules to depend on scoped modules" could look like this:

The discussion of this also went on later in the thread. It takes up about 40% of all comments,

Does this mean we can "fork" public modules?

No. This has been brought up by several people in discussion as a problem they are seeing now, but scoped modules does not solve that particular problem. That's not to say it won't be addressed at some point in the future

How will transferring between namespaces work?

This is something that was brought up by Emily Rose in a few comments and later addressed by Isaac and Forrest of npm Inc. There is subtly to this problem that was only recently implemented by Github after several years of feature requests. This suggests that perhaps it is more complicated than may be assumed so far.

Painting a moving picture

This is just a snapshot of the current discussion as of the time of writing this post! If you want to read up on the future of the discussion it ended at this comment when this was published. We will try to keep it up to date as this unfolds, but the most important thing is that this is not yet set in stone! Go give your opinion to help us shape things that matter!

Other popular posts

- Scaling Isomorphic Javascript Code - Keep a node.js server up with Forever - Package.json dependencies done right - npm cheat sheet - 6 Must Have Node.js Modules Try our service
get $20