The Nodesource Blog

#shoptalk Subscribe

Your first Node.js package

This is pretty simple, let's dive in!

Has someone already written this package?

It might be worth saving yourself some time and doing a couple of searches for the package you are looking for.

As of this writing there are ~86k packages in npm and there is a good chance someone has done something similar to what you are building.

Some good places to search are: http://npmjs.org, http://node-modules.com, and http://npmsearch.com. There is also npm search on the command-line which you may find useful.

Choose a name

Find a name that isn't taken and clearly describes what your package is doing. You'll probably not want to use your-first-node-package as below, but for example's sake that is what we will be using.

Choose a descriptive name!

$ npm view your-first-node-package
npm ERR! 404 'your-first-node-package' is not in the npm registry.
...

Woohoo, that name is not taken, let's take it.

Project initialization

It's probably best if you create a GitHub repository before initializing your project. That way when we run npm init, it will already know what repository you're pulling from and your git remote will be properly setup to track origin/master.

If that was all mumbo-jumbo, then it might be wise to have the git cheatsheet on hand.

$ git clone git@github.com:user/your-first-node-package.git
$ cd your-first-node-package

OK, now we are ready to initialize package.json which will let npm know what the name of your package is as well as what dependencies it uses

$ 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 <pkg> --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: (your-first-node-package)
version: (0.0.0)
description: My very first package
entry point: (index.js)
test command:
git repository: (https://github.com/user/your-first-node-package.git)
keywords:
author: Elijah Insua <tmpvar@gmail.com> (http://tmpvar.com)
license: (ISC)
About to write to /Users/tmpvar/your-first-node-package/package.json:

{
  "name": "your-first-node-package",
  "version": "0.0.0",
  "description": "My very first package",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/user/your-first-node-package.git"
  },
  "author": "Elijah Insua <tmpvar@gmail.com> (http://tmpvar.com)",
  "license": "MIT"
}


Is this ok? (yes)

npm init will ask you a couple of questions. Once you've finished filling them out you can take a peek at the package.json file it generated to see what it actually did.

$ cat package.json
{
  "name": "your-first-node-package",
  "version": "0.0.0",
  "description": "very first package",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/user/your-first-node-package.git"
  },
  "author": "Elijah Insua <tmpvar@gmail.com> (http://tmpvar.com)",
  "license": "MIT"
}

You can also manually edit this file if you need to. A good reason to do this is if you decide that your name is not specific enough or if the name you chose has been taken by the time you are ready to publish. You might also want to add a "test" script later on or bump the "version", although you can also use npm version for that!

package.json is a config for installing packages and resolving dependencies, but there are also packages that use it to configure other aspects of your package's lifecycle.

Code time

A word of advice: packages should do **one thing**. If you have a `lib` directory with a grab-bag of utilities and other _stuff_ in there, you should probably break those out into their own packages. Packages should be easy to digest and focused on the task they were created to perform.

By splitting individual units of functionality out into their own packages you are being a good Node.js citizen by allowing those who come after you to pick and choose how they want to build applications. Not only that—smaller packages allow faster iteration, focused documentation, and generally better test coverage (it is easier to test small packages)!

The Hello World package

So let's create a new file (module) index.js and make it compute the area of a rectangle. Why? Because it's a really easy demo!

index.js

module.exports = function(width, height) {
  return width * height;
};

While the filename here is index.js, you could name it whatever you want. If you change it you should update package.json's "main" property to match.

What is that module.exports thing?

When Node.js loads your module it's actually wrapping it in a function that looks sort of like:

function(__dirname, __filename, module, exports, require) {
// ...
}

Where __dirname and __filename are the current directory and filename of the module being loaded.

require() is a function that will synchronously load another package or module from the filesystem and return it. The package or module will be cached when first loaded, so subsequent calls to require() for that package or module in your Node.js application will not need to re-read the file.

module.exports provides a way for modules to expose functionality. Let's take a look at how this would work with our example.

Node.js REPL

If you run node in a terminal, you will enter an interactive JavaScript prompt called the Node.js REPL (Read Eval Print Loop). We'll be using this prompt to test our new package—it goes something like this:

$ node
> var area = require('./index.js');
undefined
> area(2,4)
8
>
(^C again to quit)
>

(Hint: press Ctrl+C twice to exit the REPL.)

Because we set module.exports to a function, it is the only thing exported. We can then call it directly!

Publish time

If you are a new user:

$ npm adduser <your username>

Follow the steps and you'll have an account that lets you publish to the npm registry!

Let's get this package out into the world!

OK, we've made a package! Let's publish it on the npm registry so anyone can use it.

$ git add package.json index.js
$ git commit -m "prepare for 1.0.0"
$ npm version 1.0.0
v1.0.0
$ git push && git push --tags
$ npm publish

And that's it!

Summary

We were able to build a function that computes the area of a rectangle and published it in the npm registry so other people could use it in their projects.

This is a very basic workflow and after you do it a couple of times it becomes ingrained in your muscle memory!

Homework