npm Blog (Archive)

The npm blog has been discontinued.

Updates from the npm team are now published on the GitHub Blog and the GitHub Changelog.

The right tool for the job: why not to use version control hosting for packages

You may know that it’s possible to publish and work with packages stored on version control hosting, such as GitHub, BitBucket, or GitLab. Based on this, you may wonder whether to use such a repository as your own npm package registry. You wouldn’t be the first person with that idea!

This post helps explain the implications of using version control hosting for packages, and answers some common questions that come up when you’re considering how best to help your collaborators discover and re-use packages.

Wait, you can do that? (Yes.)

npm is a package manager for many (mostly web dev-y, javascript-y) things, which is to say that npm is a collection of humans and software that make publishing and using things called “packages” easier for other humans and software.

Part of npm consists of a registry, where a lot of the packages that npm users install live — 379,000+, in fact — but this is not where all of them live.

As part of our commitment to open source, npm has always allowed users to set up alternative registries to which they can publish packages and from which they can install. In fact, this is a part of how npm Enterprise works, and there are many alternative registries out in the wild.

git Dependencies

In addition to using alternative registries, npm also supports using a git address to point to packages stored on version control hosting such as GitHub, BitBucket, or GitLab. You can use this functionality alongside the npm registry (or another registry of your choosing). For example, you could have a package.json that looks like this:

{
  "name": "my-awesome-app",
  "version": "3.0.0",
  "description": "there's an app for that- and this is it!",
  "main": "index.js",
  "author": "ag_dubs <ashley@npmjs.com>",
  "license": "ISC",
  "dependencies": {
    "express": "^4.14.0",
    "my-secret-auth-package": "git@github.com:ashleygwilliams/my-secret-auth-package.git"
  }
}

If you and your company are already using GitHub, or something like it, for version control, it might occur to you that using it as your package registry would be a simple solution — particularly if you’re already paying GitHub for private repositories!

A frequently asked question:

Why should I pay for private packages when I can simply use a private GitHub registry?

The rest of this article aims to answer that question — but here’s a quick rundown:

Meet the Registry

npm would be a terrible version control service. — C.J. Silverio, CTO, npm, Inc.

Remember how I described npm as a collection of software and humans? This was a deliberately strange move on my part. I made it primarily because many people do not realize that npm extends beyond the CLI tool you use to type npm install into your terminal. npm is a company — with many people, working on many things! The npm CLI is just one project among many.

In fact, npm’s main product is the npm Registry, a very large and semi-elaborate set of services that enable both the npm CLI client and the npm website to function. Long ago, the npm Registry used to be a simple Couch application built on top of CouchDB, but over the years, it has grown and changed, specifically for the purposes of improving uptime and performance.

Even just a brief glance at some of the data around registry activity reveals pretty awesome numbers. If you compare numbers from November 1, 2015 to November 1, 2016, you’d watch the rolling 365-day downloads count jump from 18B to 52B, roughly 300% growth! And if you think that number is big, go back one more year to 2014, when there were only 3.4B rolling weekly downloads. I’ll do the math for you: that’s 1500% growth over just 2 years!

downloads

A growth in scale can often threaten the uptime of a service, but on that metric, the npm registry has really shone. Current uptime is better than 99.95%.

If you want to check out the uptime on our services, take a look at http://ping.npmjs.com/. (And for status issues, always check out http://status.npmjs.com).

ping

Showdown!: git vs the npm Registry

There’s no question that npm is specifically designed to serve all the uses a package manager could need — but what about GitHub?

GitHub is a version control and collaboration product. Many of us know and love it, but it isn’t designed to be a package manager. Do those differing product goals make a difference in feature set and performance? Yep.

Why? Semantic versioning

In the above example, you might be quick to note that using a git dependency means that you need to replace the semver range indication for that dependency.

One of the main drawbacks to using a git dependency is that you can’t leverage semantic versioning. If you use a git dependency, you can pin to a commit or a branch, but you can’t use the language of semver to describe that decision. One of the drawbacks is that this makes it much more difficult for you and other devs to communicate and understand the version of each dependency your application needs. It also means that things like patch or minor release updates to that dependency won’t automatically be brought into your application the way a dependency that was specified as ^X.0.0 in your package.json (the default) might.

This means that using a git url to specify a dependency, instead of a language specifically designed to do it, takes more time, introduces more room for confusion, and will make your team less productive.

Why? npm install performance

It’s true that not everyone loves semantic versioning — it’s a complicated and often imperfect system, so losing that feature might not be a deal breaker for everyone. But assuming you were willing to forgo semantic versioning, the next question is: given that the npm registry is designed for installs, what’s the difference in performance between installing git dependencies vs. npm dependencies.

To answer the question, I wrote a test to see exactly what that difference was. You can find the code for that test here.

I took two common and popular frameworks, express and angular2, copied their package.jsons, then made a version for each where I replaced all the primary dependencies with git URLs. I then wrote a shell script which timed the following sitations using the time utility:

In summary, this script runs a benchmark on the length of time an npm install takes, depending on whether the primary dependencies are git dependencies (fetched from GitHub) or npm dependencies (fetched from the npm registry). For added comparison, it also runs tests to see the effect caching has on both scenarios.

The goal of this benchmark was to note the performance cost of using private git repos instead of private npm packages.

As of 6 December 2016, these were the results, as run on TravisCI, using Node 4.6.2 and npm 3.10.9: (log file):

Install Time Results (seconds)

angular2 express
git with empty cache 38.713 26.793
npm with empty cache 17.973 10.033
git with all cached 29.228 16.223
npm with all cached 13.403 7.197

Faster, but by how much?

As you can see, applications using npm depdendencies were much faster than those using git dependencies. But how much faster?

Let’s calculate what percentage faster npm is compared to git using the following assignments and calculation:

Tgit = installation time for git dependencies
Tnpm = installation time for npm dependencies

(Tnpm/Tgit) - 1 = x

... where x = the percentage (in decimal) that Tnpm is faster than Tgit

Applying this to the generated data we get

angular2 express
empty cache 53.574% 62.554%
all cached 54.143% 55.637%

If we average these we’ll find that on average, using npm dependencies is around 56.5% faster than using git dependencies.

What it means

So — what to conclude from all of this?

First: if you didn’t know that you could use git dependencies with npm… now you do! There are plenty of good reasons to use git dependencies, and npm is commited not only to ensuring that the CLI always supports them, but also to continuously improving the performance of installing them.

That being said, if your team is looking for improved performace and team communication, among other boons, you’ll want to leverage the npm registry. In summary, the npm registry offers an improved performance over git dependencies because:

If you’re currently using private git repos as dependencies in your application, I’d strongly encourage you to take a look at npm’s private packages and orgs products. In addition to making your team more productive, you’ll be supporting the open source npm ecosystem and the JavaScript community, and who doesn’t like doing that?