Update: 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 thenode_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: [email protected]
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!”.
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