npm has become wildly popular for managing JavaScript packages. It started in the backend world but has since grown to include frontend libraries as well. And now we have another issue: it’s hard to find a package your need because there are so many, and you end up creating a new one increasing the number of packages even more. Better search engines, like npms, help a lot, but the problem still exists.
To develop your own package or not is a hard decision you have to make, with pros and cons on both sides.
The point of a package manager like npm is to avoid unnecessary development effort. Instead of developing every piece of code yourself, you consume readymade functionality using npm. This isn’t without its problems as you have to research and test your options.
npm ecosystem is vast and it hosts multiple smaller communities, such as AngularJS, Ember, or React. Certain utility libraries, like Lodash, are valuable across these boundaries. npm offers a lot of choice and it’s not uncommon to have tens of options available to address your specific problem.
When you are confronted with a technical problem, you have at least the following options:
If you get lucky, there may be a package that addresses your problem exactly. Then the problem is more about finding it and verifying the package quality. To do this, you may want to walk through the project code, check out its issue tracker, and see if the project is in a vital state.
There are several pros and cons to this approach:
Pros:
Cons:
Services like npm trends and npm-stat can help you to evaluate packages popularity.
Often you’ll find something that almost fits. Improving an existing project is usually simpler than developing your own from scratch. If the project is in a healthy state, there’s a good chance that the work gets merged.
If it’s a bug or a small feature, you can send a pull request right away, otherwise you should discuss the feature with the project maintainers. Normally this is done by opening an issue at the project issue tracker, explaining the use case, and the desired outcome. This may lead to further insights and avoid redundant effort as you spend time on design.
The pros and cons are similar as before but there are a few more:
Pros:
Cons:
Sometimes the project you want to contribute could have been abandoned by its authors or they are too busy to maintain it actively.
If you see value in the project and want to take over the maintenance, get in touch with the authors and ask them to give you rights to the repository and an npm package.
Sometimes they would like to continue to work under some conditions: contracting is one option.
This time pros and cons are more involved as you become more active.
Pros:
Cons:
You can also fork the project. This can be done in a few ways:
@org/some-package
that contains the modified version. The maintenance cost is lower than when taking over a package because you’ll be the only user of your package.Original licensing can become problematic. This applies to so called copyleft (or viral) licenses, like GPL and stricter AGPL, which put restrictions on the usage. If you fork a project like this, note that the license still applies!
Over time the original project might become active again and you could look into merging the efforts. This has happened in the past with bigger projects like Node and io.js or ayo. A fork can revitalize a stagnant project and force it to pick up pace again.
This time around you gain control but also split effort.
Pros:
Cons:
Learn different licensing options by reading The Legal Side of Open Source, Open-Source Licensing For Dummies and Producing OSS: Legal Matters chapter.
If there’s nothing that fits your purposes you may want to develop on your own package. Sometimes people end up developing their own packages because they aren’t aware of the existing options. Discoverability is a real problem given the amount of packages available.
One of early stage problems is figuring out a good name for a package. npm root namespace has become crowded and it can be difficult to find a free name. Also, you may have to worry about existing trademarks to avoid problems later on. By skipping this you may have to rename your package later as happened for Jade which had to rename as Pug.
Scoped packages could solve the naming issue. A scoped package name looks like @scope/name
and allows you to group a series of packages behind a namespace. Scoping allows you to manage people that have access to these packages easily. Scopes are freely available for open source projects.
DefinitelyTyped and webpack-blocks are examples of projects using scoped packages.
The pros and cons are roughly opposite compared to using an existing package:
Pros:
Cons:
Most of the time you’ll use these commands:
npm install <package> --save
or npm i <package> -S
.npm install <package> --save-dev
or npm i <package> -D
<package>@<version>
will install a specific version.
Pointing to a package by its name and version is not the only way:
<git repository>#<reference>
points to a Git repository and a Git reference.<github user>/<project>#<reference>
shortcut points to GitHub in a similar way.<github user>/<project>#pull/<id>/head
points to a specific GitHub pull request.<reference>
can be either a commit hash, a tag, or a branch.
The Package Authoring Techniques chapter shows how to set up your package to support consumption beyond Git.
To avoid sharing all your packages in public, npm allows you to maintain private packages through their commercial offering. Another option is to use a tool like verdaccio which allows you to maintain a private server that can also work as a cache for npm. You can also override public packages using it.
npm’s lookup algorithm is another aspect that’s good to understand. Sometimes this can explain certain errors, and it also leads to good practices, such as preferring local dependencies over global ones. The basic algorithm goes as below:
npm root
.On a package level, npm resolves to a file as below:
main
field. If it doesn’t exist, default to main
file.The general lookup algorithm respects an environment variable NODE_PATH
. If you are using Unix, you can patch it through NODE_PATH=./demo:$NODE_PATH
. The call can be included at the beginning of a package.json scripts to tweak NODE_PATH
temporarily.
Installing global packages can lead to surprising behavior. If you have a package installed both globally and if a project happens to contain it, executing associated terminal command (saywebpack
) points to the version of the project. It doesn’t work unless the global package exists. Also note thatwebpack
in npm script will call a local package if it exists and fallbacks to a global one otherwise.
app-module-path allows you adjust Node module lookup within JavaScript and this can be an alternative to patching NODE_PATH
.
Before writing your own package, investigate existing packages: you may find that a new package is not required and you can contribute to a thriving one or even use it as is. Even forking an existing package can be a good option that may save you a lot of work.
You’ll learn how npm packages are structured in the next chapter.
This book is available through Leanpub. By purchasing the book you support the development of further content.