Essential Guide for npm Developers: Packaging and Publishing
This tutorial is going to serve as a guide for developers.
Description
This tutorial is for those that want to either develop (publish/deploy) your project.
About These Documents
All these documents are man pages. If you have installed npm, you should be able to run man npm-thing or npm help thing to get the documentation on a particular topic.
What is a package
A package is defined thus:
- A folder which has a program described by a package.json file.
- A gzipped tarball that contains (a).
- A url that will resolve to (b).
- A <name>@<version> that has been published on the registry with (c).
- A <name>@<tag> that points to (d).
- A <name> that contains a latest tag satisfying (e).
- A git url that results in (a) when it is cloned.
Even if don't publish your package, you can still get most of the benefits of using npm if you just want to write a node program (a), and perhaps if you also want to be able to easily install it anywhere after packing it up into a tarball (b).
A git url can be of the form:
git://github.com/user/project.git#commit-ish
git+ssh://user@hostname:project.git#commit-ish
git+http://user@hostname/project/blah.git#commit-ish
git+https://user@hostname/project/blah.git#commit-ish
The commit-ish may be any tag, sha, or branch that can be supplied as an argument to git checkout. The default is usually master.
The package.json File
You will need to have a package.json file in the root of your project to do much of anything with npm. This is basically the whole interface.
Basically what you need is:
- name: This has to be a string that identifies your project. The name should not specify that it run in node or it's a JavaScript file. Use the "engines" field to explicitly state the versions of node (or whatever else) that your program requires,and it will be assumed that it's JavaScript.
And the name of your project does not need to match your github repository name.
So, node-bar and foo-js are bad names. bar or foo are better. - version: This is a semver-compatible version.
- engines: this specifies the versions of node (or whatever else) that your program runs on. The node API changes often, and there could be bugs or new functionality that you now depend on. Be sure to be explicit.
- author: Take some credit for your work.
- scripts: The script object is where you should put special installation or compilation scripts. You should have at least a basic smoke-test command as the "scripts.test" field.
- main: The main is where you will specify a single module that serves as the entry point to your program (like what "bar" package gives you at require("bar").
- directories: The directory is an object mapping names to folders. The best directory to include are "lib" and "doc", but if you are suing "man" to specify a folder full of man pages, they will get installed just like these ones.
You can also use npm init in the root of your package in order to get you started with a pretty basic package.json file.
Keeping files out of your package
You should use a .npmignore file to keep stuff out of your package. If you don't have a .npmignore file, but you have a .gitignore file, then npm ignores the things matched by the .gitignore file. If you wish to include something that is excluded by your .gitignore file, you can create an empty .npmignore file which will override it. Much like git, npm will look for .npmignore and .gitignore files in all of your package subdirectories, not jsut the root directory.
.npmignore files and .gitignore files have the same pattern rules:
- Blank lines or lines which start with # will be ignored.
- Standard glob patterns will work.
- You can end patterns with a forward slash / to specify that it is a directory.
- You can also negate a pattern by starting it with an exclamation point !.
The following paths and files are ignored by default, so there will be no need to add them to .npmignore explicitly:
- .*.swp
- ._*
- .DS_Store
- .git
- .hg
- .npmrc
- .lock-wscript
- .svn
- .wafpickle-*
- config.gypi
- CVS
- npm-debug.log
Additionally, everything that is in node_modules is ignored, with the exception of bundled dependencies. npm will automatically handle this for you, so do not bother adding node_modules to .npmignore.
The following paths and files will never be ignored, hence adding them to .npmignore is pointless:
- package.json
- README (and its variants)
- CHANGELOG (and its variants)
- LICENSE / LICENCE
If, given the structure of your project, and you find that .npmignore is a maintenance headache, you might try populating the files property of package.json instead, which is an array of directory names or file that should be included in your package. Sometimes it is easier to manage a whitelist than a blacklist.
Testing if your .npmignore or files config works
If you want to double check that your package will include only the files that you intend it to when published, you may run the npm pack command locally which will generate a tarball in the working directory, the same way it will for publishing.
Link Packages
The npm link command is designed to install a development package and view the changes in real time without having to keep re-installing it. (You have to either re-link or npm rebuild -g to update compiled packages.)
Before Publishing: Ensure that Your Package Installs and Works
This is very important.
If you cannot install it locally, you will have problems when you are trying to publish it. Or, even worse, you will be able to publish it, but your package will be a broken or pointless package. So, publishing without testing is not advisable.
Do this in the root of your package:
npm install . -g
That will show you that it is working. If you would rather just create a symlink package that points to your working directory, then you should do this:
npm link
You should use npm ls -g to see if it's there.
If you need to test a local install, you should go into some other folder, and then do this:
cd ../some-other-folder```
```npm install ../my-package
This will install it locally into the node_modules folder in that other place.
Then inside the node-repl, try to use require("my-thing") to bring in your module's main module.
Create a User Account
This will create a user with the adduser command. It works like this:
npm adduser
and then follow the prompts to create a user.
Publish your package
This is the easy part. In the root of your package folder, do this:
npm publish
You can give the publish a url to a tarball, or a filename of a tarball, or a path to a folder.
It should be noted that pretty much everything in that folder is exposed by default. So, if you have secret stuff there, you should use a .npmignore file to list out the globs to ignore, or you can publish from a fresh checkout.
Previous:
Comprehensive Guide to npm Configuration Settings.
Next:
How to handle npm Module name disputes: A Comprehensive Guide.
- Weekly Trends and Language Statistics
- Weekly Trends and Language Statistics