Book Image

Mastering Node.js

By : Sandro Pasquali
Book Image

Mastering Node.js

By: Sandro Pasquali

Overview of this book

Node.js is a modern development stack focused on providing an easy way to build scalable network software. Backed by a growing number of large companies and a rapidly increasing developer base, Node is revolutionizing the way that software is being built today. Powered by Google's V8 engine and built out of C++ modules, this is a JavaScript environment for the enterprise.Mastering Node.js will take the reader deep into this exciting development environment. Beginning with a comprehensive breakdown of its innovative non-blocking evented design, Node's structure is explained in detail, laying out how its blazingly fast I/O performance simplifies the creation of fast servers, scalable architectures, and responsive web applications.Mastering Node.js takes you through a concise yet thorough tour of Node's innovative evented non-blocking design, showing you how to build professional applications with the help of detailed examples.Learn how to integrate your applications with Facebook and Twitter, Amazon and Google, creating social apps and programs reaching thousands of collaborators on the cloud. See how the Express and Path frameworks make the creation of professional web applications painless. Set up one, two, or an entire server cluster with just a few lines of code, ready to scale as soon as you're ready to launch. Move data seamlessly between databases and file systems, between clients, and across network protocols, using a beautifully designed, consistent, and predictable set of tools.Mastering Node.js contains all of the examples and explanations you'll need to build applications in a short amount of time and at a low cost, running on a scale and speed that would have been nearly impossible just a few years ago.
Table of Contents (20 chapters)
Mastering Node.js
Credits
About the Author
Acknowledgments
About the Reviewers
www.PacktPub.com
Preface
Index

Using npm


As mentioned when discussing how Node does path lookups, modules may be contained within a folder. If you are developing a program as a module for others to use you should bundle that module within its own folder and publish it. The npm package management system is designed to help you do just that.

As we've seen throughout the examples in this book, a package.json file describes a module, usefully documenting the module's name, version number, dependencies, and so forth. It must exist if you would like to publish your package via npm. In this section we will investigate the key properties of this file, and offer some hints and tips on how to configure and distribute your modules.

Note

Try npm help json to fetch detailed documentation for all the available package.json fields, or visit https://npmjs.org/doc/json.html.

A package.json file must conform to the JSON specification. For example, properties and values must be double-quoted.

Initializing a package file

You can create a package file by hand, or use the handy npm init command-line tool, which will prompt you for a series of values and automatically generate a package.json file. Let's run through some of these values:

  • name: (Required) This string is what will be passed to require() in order to load your module. Make it short and descriptive, using only alphanumeric characters—this name will be used in URLs, command line arguments, and folder names. Try to avoid using "js" or "node" in the name.

  • version: (Required) npm uses semantic versioning, where these are all valid:

    • >=1.0.2 <2.1.2

    • 2.1.x

    • ~1.2

    Note

    For more information on version numbers, visit https://npmjs.org/doc/misc/semver.html.

  • description: When people search npmjs.org for packages, this is what they will read. Make it short and descriptive.

  • entry point: This is the file that should set module.exports—it defines where the module object definition resides.

  • keywords: A comma-separated list of keywords that will help others find your module in the registry.

  • license: Node is an open community that likes permissive licenses. "MIT" and "BSD" are good ones here.

You might also want to set the private field to true while you are developing your module. This ensures that npm will refuse to publish it, avoiding accidental releases of incomplete or time-sensitive code.

Using scripts

npm is ultimately a build tool, and the scripts field in your package file allows you to set various build directives executed at some point following certain npm commands. For example, you might want to minify JavaScript, or execute some other processes that build dependencies that your module will need whenever npm install is executed. The available directives are:

  • prepublish, publish, postpublish: Run by the npm publish command.

  • preinstall, install, postinstall: Run by the npm install command.

  • preuninstall, uninstall, postuninstall: Run by the npm uninstall command.

  • preupdate, update, postupdate: Run by the npm update command.

  • pretest, test, posttest: Run by the npm test command.

  • prestop, stop, poststop: Run by the npm stop command.

  • prestart, start, poststart: Run by the npm start command.

  • prerestart, restart, postrestart: Run by the npm restart command. Note that npm restart will run the stop and start scripts if no restart script is provided.

It should be clear that the commands with prefix pre will run before, and the commands with prefix post will run after their primary command (such as publish) is executed.

Note

Package files demonstrating the use of script directives can be found in the mocha-zombie folder in the code bundle for Chapter 9, Testing Your Application.

Declaring dependencies

It is likely that a given module will itself depend on other modules. These dependencies are declared within a package.json file using four related properties, which are:

  • dependencies: The core dependencies of your module should reside here.

  • devDependencies: Some modules are only needed during development (and not in production), such as those used for testing. Declare those modules here.

    Note

    npm install will always install both dependencies and devDependencies. To install an npm package without loading devDependencies, use the command npm install --production.

  • bundledDependencies: Node is changing rapidly, as are npm packages. You may want to lock a certain bundle of dependencies into a single bundled file and have those published with your package, such that they will not change via the normal npm update process.

  • optionalDependencies: Contains modules that are optional. If these modules cannot be found or installed the build process will not stop (as it will with other dependency load failures). You can then check for this module's existence in your application code.

Dependencies are normally defined with a npm package name followed by versioning information:

"dependencies" : {
  "express" : "3.3.5"
}

However they can also point to a tarball:

"foo" : "http://foo.com/foo.tar.gz"

You can point to a GitHub repository:

"herder": "git://github.com/sandro-pasquali/herder.git#master"

Or even the shortcut:

"herder": "sandro-pasquali/herder"

Note

These GitHub paths are also available to npm install. For example, npm install sandro-pasquali/herder.

Additionally, in cases where only those with proper authentication are able to install a module, the following format can be used to source secure repositories:

"dependencies": {
  "a-private-repo": "git+ssh://[email protected]:user/repo.git#master"
}

By properly organizing your dependencies by type, and intelligently sourcing those dependencies, build requirements should be easy to accommodate using Node's package system.

Publishing packages

In order to publish to npm, you will need to create a user. npm adduser will trigger a series of prompts requesting your name, e-mail, and password. You may then use this command on multiple machines to authorize the same user account.

Note

To reset your npm password visit https://npmjs.org/forgot.

Once you have authenticated with npm you will be able to publish your packages using the command npm publish. The easiest path is to run this command from your package folder. You may also target another folder for publishing (remember that a package.json file must exist in that folder).

You may also publish a gzipped TAR archive containing a properly configured package folder.

Note that if the version field of the current package.json file is lower or equal to that of the existing, published package npm will complain and refuse to publish. You can override this by using the --force argument with publish, but you probably want to update the version and republish.

To remove a package use npm unpublish <name>[@<version>]. Note that once a package is published other developers may depend on it. For this reason you are strongly discouraged from removing packages that others are using. If what you want to do is discourage the use of a version, use npm deprecate <name>[@<version>] <message>.

To further assist collaboration, npm allows multiple owners to be set for a package:

  • npm owner ls <package name>: Lists the users with access to a module.

  • npm owner add <user> <package name>: The added owner will have full access, including the ability to modify the package and add other owners.

  • npm owner rm <user> <package name>: Removes an owner and immediately revokes all privileges.

All owners have equal privileges—special access controls are unavailable, such as being able to give write but not delete access.

Globally installing packages and binaries

Some Node modules are useful as command-line programs. Rather than requiring something such as > node module.js to run a program, we might want to simply type > module on the console and have the program execute. In other words, we might want to treat a module as an executable file installed on the system $PATH and therefore accessible from anywhere. There are two ways to achieve this using npm.

The first and simplest way is to install a package using the -g (global) argument:

npm install -g module

If a package is intended as a command-line application that should be installed globally, it is a good idea to set the preferGlobal property of your package.json file to true. The module will still install locally, but users will be warned about its global intentions.

Another way to ensure global access is by setting a package's bin property:

"name": "aModule",
"bin" : {
  "aModule" : "./path/to/program"
}

When this module is installed, aModule will be understood as a global CLI command. Any number of such programs may be mapped to bin. As a shortcut, a single program can be mapped like so:

"name": "aModule",
"bin" : "./path/to/program"

In this case the name of the package itself (aModule) will be understood as the active command.

Sharing repositories

Node modules are often stored in version control systems, allowing several developers to manage package code. For this reason the repository field of package.json can be used to point developers to such a repository, should collaboration be desired. For example:

"repository" : {
  "type" : "git",
  "url" : "http://github.com/sandro-pasquali/herder.git"
}
"repository" : {
  "type" : "svn",
  "url" : "http://v8.googlecode.com/svn/trunk/"
}

Similarly, you might want to point users to where bug reports should be filed by using the bugs field:

"bugs": {
  "url": "https://github.com/sandro-pasquali/herder/issues"
}