npm tips and tricks for managing Node.js packages
Marco Franssen

Loading...
Marco Franssen

In my previous post, I showed you how easily you can create a simple web server using Node.js. In this post, I want to show you some more advanced ways to use npm (node package manager) to manage and publish your packages.
With node package manager, you can get your project started even more quickly using the npm init command. So let's get started by opening a command prompt (on Windows, open the Node.js command prompt). Create a new folder and navigate into it. Then execute the following command and answer the questions, or press Enter to accept the defaults.
Your environment has been set up for using Node.js 0.10.17 (x64) and npm.
Press any key to continue . . .
C:\Users\Marco> mkdir NodeJsPackageExample
C:\Users\Marco> cd NodeJsPackageExample
C:\Users\Marco\NodeJsPackageExample> npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.
See `npm help json` for definitive documentation on these fields
and exactly what they do.
Use `npm install --save` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
name: (NodeJsPackageExample) node-js-package-example
version: (0.0.0) 0.0.1
description: Total package awesomeness
entry point: (index.js)
test command:
git repository:
keywords: package, awesomeness
author: Marco Franssen
license: (BSD-2-Clause) MIT
About to write to C:\Users\Marco\NodeJsPackageExample\package.json:
{
"name": "node-js-package-example",
"version": "0.0.1",
"description": "Total package awesomeness",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"package",
"awesomeness"
],
"author": "Marco Franssen",
"license": "MIT"
}
Is this ok? (yes) yesAfter answering the questions, your result should look something like the example above. As you can see, I changed the default name. By default, node package manager uses the folder name. Play around to get the result you want. You can also edit package.json after it has been created.
Why do we need this package.json file?
The answer is simple… When we put our code in source control (Git, SVN, TFS), we don't want to commit all our third-party packages. We also don't want to ship all our dependencies as part of our own package when we release it to the npm registry. Team members or users who check out your code or download your package still need those dependencies, and this is where packages.json comes in. After downloading the package, they simply execute npm install. This downloads the dependencies based on your package.json file.
So let's continue with some more npm tips and tricks. The second command you may already have seen while running npm init is npm install --save. In the npm version used here, this installs a package and saves it in package.json. Without the --save option, the package is not added to package.json. Let's start by adding the express package, which we also used in the previous post.
C:\Users\Marco\NodeJsPackageExample> npm install --save express
npm WARN package.json node-js-package-example@0.0.1 No repository field.
npm WARN package.json node-js-package-example@0.0.1 No README data
npm http GET https://registry.npmjs.org/express
...
...
left for brevity
...
...
express@3.4.6 node_modules\express
├── methods@0.1.0
├── range-parser@0.0.4
├── cookie-signature@1.0.1
├── fresh@0.2.0
├── debug@0.7.4
├── buffer-crc32@0.2.1
├── cookie@0.1.0
├── mkdirp@0.3.5
├── commander@1.3.2 (keypress@0.1.0)
├── send@0.1.4 (mime@1.2.11)
└── connect@2.11.2 (uid2@0.0.3, pause@0.0.1, qs@0.6.5, raw-body@1.1.2, bytes@0.2
.1, negotiator@0.3.0, multiparty@2.2.0)As you can see, the express package is installed along with all its dependencies. In our package.json, we can see the dependency that was added.
{
"name": "node-js-package-example",
"version": "0.0.1",
"description": "Total package awesomeness",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": ["package", "awesomeness"],
"author": "Marco Franssen",
"license": "MIT",
"dependencies": {
"express": "~3.4.6"
}
}Now you know how to install a package and save it to package.json. To uninstall a package and remove it from your package file, just execute the npm uninstall --save command.
If, like me, you skipped the repository during npm init, you will have seen two warnings. Let's resolve both by adding a repository to package.json and a Readme.md file to the root of our package.
"repository": {
"type": "git",
"url": "https://github.com/marcofranssen/NodeJsPackageExample.git"
}Don't forget to add some content to your Readme.md file; otherwise, npm won't be satisfied. A title and a short description should be enough.
When deploying a package to a server, you don't want to deploy your development packages too. An example of a development package is grunt. We want to save these packages separately so our fellow developers can install them while our production server can skip them.
`C:\Users\Marco\NodeJsPackageExample> npm install --save-dev grunt
npm http GET https://registry.npmjs.org/grunt
...
...
left for brevity
...
...
grunt@0.4.2 node_modules\grunt
├── dateformat@1.0.2-1.2.3
├── which@1.0.5
├── eventemitter2@0.4.13
├── getobject@0.1.0
├── colors@0.6.2
├── hooker@0.2.3
├── async@0.1.22
├── exit@0.1.2
├── coffee-script@1.3.3
├── underscore.string@2.2.1
├── iconv-lite@0.2.11
├── lodash@0.9.2
├── findup-sync@0.1.2 (lodash@1.0.1)
├── nopt@1.0.10 (abbrev@1.0.4)
├── rimraf@2.0.3 (graceful-fs@1.1.14)
├── glob@3.1.21 (inherits@1.0.0, graceful-fs@1.2.3)
├── minimatch@0.2.12 (sigmund@1.0.0, lru-cache@2.5.0)
└── js-yaml@2.0.5 (esprima@1.0.4, argparse@0.1.15)`As you can see, all dependencies of Grunt are automatically installed, and a new property is added to your package.json file.
"devDependencies": {
"grunt": "~0.4.2"
}With grunt installed, you can speed up development even more by automating tasks such as running tests, minifying files, and compiling Less or Sass. I'd like to challenge you to share your grunt scripts with me and the rest of the developer community by leaving a comment on this post. For more help with Grunt, visit http://gruntjs.com/.
If your package is not intended to be shared or reused through the npm registry, protect yourself by adding the following setting to your package.json.
"private": trueThis prevents you from accidentally publishing your package to the npm registry.
While working on your awesome package, you probably want to update your dependencies before publishing so you are using the latest available versions.
To check whether any package updates are available, you can run the following command.
C:\Users\Marco\NodeJsPackageExample> npm outdated
npm http GET https://registry.npmjs.org/express
npm http 200 https://registry.npmjs.org/express
npm http GET https://registry.npmjs.org/express/-/express-3.4.7.tgz
npm http 200 https://registry.npmjs.org/express/-/express-3.4.7.tgz
express@3.4.7 node_modules\express current=3.4.6`As you can see, there is a new release of the express package. Since it is a patch release (an increment of the third version number), I decide to update this package.
C:\Users\Marco\NodeJsPackageExample> npm update --save express
npm http GET https://registry.npmjs.org/express
npm http 304 https://registry.npmjs.org/express
npm http GET https://registry.npmjs.org/express/3.4.7
...
...
left for brevity
...
...
express@3.4.7 node_modules\express
├── methods@0.1.0
├── merge-descriptors@0.0.1
├── fresh@0.2.0
├── buffer-crc32@0.2.1
├── debug@0.7.4
├── range-parser@0.0.4
├── cookie-signature@1.0.1
├── cookie@0.1.0
├── mkdirp@0.3.5
├── commander@1.3.2 (keypress@0.1.0)
├── send@0.1.4 (mime@1.2.11)
└── connect@2.12.0 (uid2@0.0.3, pause@0.0.1, qs@0.6.6, bytes@0.2.1, batch@0.5.0,
raw-body@1.1.2, negotiator@0.3.0, multiparty@2.2.0)npm uses semantic versioning, and it is up to the package creator or publisher to follow these guidelines. Always double-check what has changed and whether your package still works after upgrading its dependencies. Usually, patch releases should be safe to install. Be more careful when upgrading to minor or major releases. More information about versioning can be found here. Make sure your own package follows these guidelines when publishing new releases, as this will help other developers update their dependencies.
Creating a package is one thing, but you probably also want to share it with the community. Sharing a package is pretty straightforward.
First, we need to set our npm author information if we haven't already done so. We can do this by executing the following commands.
C:\Users\Marco\NodeJsPackageExample> npm set init.author.name "Marco Franssen"
C:\Users\Marco\NodeJsPackageExample> npm set init.author.email "marco.franssen@gmail.com"
C:\Users\Marco\NodeJsPackageExample> npm set init.author.url "http://marcofranssen.nl"
C:\Users\Marco\NodeJsPackageExample> npm adduser
Username: marcofranssen
marcofranssen
Password:
Password:
Email: marco.franssen@gmail.com
npm http PUT https://registry.npmjs.org/-/user/org.couchdb.user:marcofranssen
npm http 409 https://registry.npmjs.org/-/user/org.couchdb.user:marcofranssen
...
...
npm http PUT https://registry.npmjs.org/-/user/org.couchdb.user:marcofranssen/-r
ev/4-84c649f53b8faf80bc10b02a190bcb64
npm http 201 https://registry.npmjs.org/-/user/org.couchdb.user:marcofranssen/-r
ev/4-84c649f53b8faf80bc10b02a190bcb64Now your user account is created, and you can publish packages to the npm registry.
The last thing left is to publish the actual package, which we can do using the following command.
C:\Users\Marco\NodeJsPackageExample> npm publish ./I had set the private flag to true in my package.json:
"private": trueSo I got the following error:
npm ERR! Error: This package has been marked as private
npm ERR! Remove the 'private' field from the package.json to publish it.When I remove this setting from my package.json and execute npm publish again, it should succeed, and my package will be listed in the npm registry.
C:\Users\Marco\NodeJsPackageExample> npm publish ./
npm http PUT https://registry.npmjs.org/node-js-package-example
npm http 201 https://registry.npmjs.org/node-js-package-example
...
...
...
npm http 201 https://registry.npmjs.org/node-js-package-example/0.0.1/-tag/latest
+ node-js-package-example@0.0.1Since the package I just published was only an example, I removed it using the following command.
C:\Users\Marco\NodeJsPackageExample> npm unpublish ./ --force
npm WARN using --force I sure hope you know what you are doing.
...
...
npm http DELETE https://registry.npmjs.org/node-js-package-example/-rev/3-366120337d
9f89cd2ca7fc0c4489281d
...
...I hope this article showed you some of the nice things you can do to quickly build your first Node.js package and publish it to the npm registry. Using npm gives you better control over your dependencies and makes it easier for you and your team to keep track of them.
Also have a look at https://npmjs.org/doc/developers.html to learn even more about npm.
Thanks for reading.
Marco Franssen
Write synchronous and asynchronous Node.js tests with Mocha, Chai assertions and Sinon spies, stubs and fake timers, then run them with Grunt.
Marco Franssen
Automate development and CI tasks with Grunt: configure a Gruntfile, run task targets, combine tasks, and watch files to rerun jobs when they change.
Marco Franssen
Build a simple Node.js web server with Express, use npm packages and nodemon during development, and serve an HTML page from a static public folder.
Marco Franssen
Connect a .NET MSBuild CI script to Jenkins, trigger builds from GitHub, configure repository access, and publish MSpec and code coverage reports.