Cloud Foundry Supports Node.js Modules with NPM

May 24, 2012 Maria Shaldibina

featured-cf-genericUpdate: Recent Changes in Node.js Modules Support

We are pleased to announce support for npm (Node Package Manager) which manages Node.js application module dependencies on CloudFoundry.com. The popularity of Node.js can be partially attributed to its strong ecosystem that has created modules for practically any programming task–from database access to payment processing. At present, there are over 10,000 node modules listed on search.nodejs.org. Any cloud that aspires to provide good support for Node.js needs to simplify the task of using node modules. With the addition of npm support, Cloud Foundry now makes it easier for you to manage modules for node applications. The normal process of creating a Node.js application requires local installation of node modules (typically in the node_modules folder inside the application), essentially making the application self-contained. You can deploy this application locally or push all its contents, including the node modules, to CloudFoundry.com. This works fine as long as the app didn’t need a node module with native dependencies, which must be compiled specifically for the target platform. The npm support described in this blog obviates the need to package module dependencies with the app and makes it possible to use modules with native dependencies.

Requirements and Limitations

In order to use the npm feature, you would need to follow a few simple steps:

  • The application must provide an npm-shrinkwrap.json file. This file can be generated with the npm shrinkwrap command and reflects the whole tree of dependencies with fixed versions. This file is a snapshot of application dependencies in the same way that Gemfile.lock serves Ruby applications. This guarantees that Cloud Foundry will provide the exact same node module versions, which avoids incompatibility issues and follows the same dependencies hierarchy.
  • By default, Cloud Foundry uses node modules if the application includes them. More concretely, if an application has a node_modules folder in its base folder, then Cloud Foundry will simply use the modules in that folder. To overwrite the existing modules in the node_modules folder, you would provide a configuration file, cloudfoundry.json, with the “ignoreNodeModules” option set to true. If the above conditions are met, Cloud Foundry will install node modules to the application during staging based on the module versions, application runtime version and npm version. If a required node module does not work with the node engine that the application is running on, the module will not be installed. Currently, in order to push the application with the node engine version 0.6.x, it needs to be explicitly specified during application push.
$ vmc push app-name --runtime=node06

If a module installation fails for some reason, Cloud Foundry will use the node module provided by the user. Besides the compatibility requirement outlined above, there may be other possible reasons for installation failures. For example, when a node module of a given version is not found in the npm registry. When an error occurs, information about the installation process along with any npm error messages can be found in the application logs.

$ vmc logs app-name
...
Installing dependencies. Node version 0.6.8
Failed getting the requested package: bcrypt@0.4.5

Note that although npm supports git URLs specified manually after

npm-shrinkwrap.json was generated, Cloud Foundry currently does not support git URLs.

Native node modules Cloud Foundry npm support also allows deployment of Node.js applications with native module dependencies. Many popular node modules such as

bcrypt, fibers and nowjs have native code that depends on the platform. So locally installed node modules that were pushed along with the application would raise platform incompatibility errors often manifested as “invalid ELF header” errors during execution. Now, if an application meets the above requirements for npm support, compiled native dependencies will be provided by Cloud Foundry to the application during an application push.

Example of npm support in action

Let’s see how npm support works. Here we have an application with the main file app.js:

var app = require("express").createServer();
var bcrypt = require("bcrypt");
app.get("/", function(req, res) {
  var salt = bcrypt.genSaltSync(10);
  var hash = bcrypt.hashSync("B4c0//", salt);
  if (bcrypt.compareSync("B4c0//", hash))
    res.send("World is safe!");
  else
    res.send("World is in trouble!");
});
var port = process.env.VCAP_APP_PORT || 3000;
app.listen(port);

And package.json that specifies our dependencies. In this example we use express, which depends on other node modules and native dependency, bcrypt.

{
  "name" : "node-dependencies-example",
  "version" : "0.1.0",
  "dependencies" : {
    "express" : "2.5.x",
    "bcrypt" : "0.5.x"
  }
}

We first verified that the application is working locally with installed module versions. We can then run the “npm shrinkwrap” command in the application’s base directory to generate the npm-shrinkwrap.json file:

{
  "name": "node-dependencies-example",
  "version": "0.1.0",
  "dependencies": {
    "express": {
      "version": "2.5.9",
      "dependencies": {
        "connect": {
          "version": "1.8.7",
          "dependencies": { "formidable": { "version": "1.0.9" } }
        },
        "mime": { "version": "1.2.4" },
        "qs": { "version": "0.4.2" },
        "mkdirp": { "version": "0.3.0" }
      }
    },
    "bcrypt": { "version": "0.5.0" }
  }
}

We can now push the application without the node_modules folder, or we can provide a cloudfoundry.json file in the application’s base directory, which sets ignoreNodeModules to true to bypass the existing node modules.

{ "ignoreNodeModules" : true }

If we push our application now, Cloud Foundry will install node modules into the application that were compiled on Cloud Foundry’s platform.

$ vmc push node-dependencies-example --runtime=node06

Note that bcrypt has different APIs for different node engines, so we have to explicitly specify the required runtime. Finally, if we go to a browser we would see the display, “World is safe!”. Node dependencies example app screenshot

To summarize, npm support is a long-awaited feature that allows you to use the full variety of node modules available today, greatly enhancing your application.

– Maria Shaldibina The Cloud Foundry Team

Don’t have a Cloud Foundry account yet? Sign up for free today

About the Author

Biography

Previous
Birchbox is looking for experienced RoR Engineers
Birchbox is looking for experienced RoR Engineers

At Pivotal Labs, one of the services we provide our clients is helping them interview and hire. Pivotal Lab...

Next
Headless && Head OK
Headless && Head OK

Helps asset pipeline testing with RSpec render_views I'm trying to test the asset pipeline configuration i...

×

Subscribe to our Newsletter

!
Thank you!
Error - something went wrong!