Since Cloud Foundry introduced npm support, we added several improvements that make deploying Node.js applications with dependencies easier, faster and more transparent to developers.
When we introduced npm support in Node.js, in addition to generating “npm-shrinkwrap.json” file with locked down dependencies you were required to remove the “node_modules” folder. If this was too disruptive, you could create an “cloudfoundry.json” file with an “ignoreNodeModules” property set to ‘true’.
This wasn’t an obvious solution. So we decided to change it. Detection of native modules is now done automatically by analyzing module contents. To lock down module versions, you can simply use the “npm shrinkwrap” command and your application is ready to be pushed with or without bundled modules. With this change, we have deprecated ignoreNodeModules property.
If you want to store your application in a git repository without node modules, the next time someone clones it, he/she can just push it to CloudFoundry.com without any modifications.
In addition to npm, we also improved our cache system. There are two levels of caching now — fetched and compiled modules. All modules that have been fetched from the npm registry are cached locally and pulled from that cache from that point on. If a module contains native code, it gets compiled on Cloud Foundry and the compiled version gets cached as well.
Based on the information from npm-shrinkwrap.json, Cloud Foundry checks if the module has been provided with the application itself. If it is there, and contains native code, it rebuilds it as needed. If the module hasn’t been provided with the app, Cloud Foundry checks the local cache for the given module, and if it needs compilation, provides the cached version.
As module contents can be modified by users, we are using hash of module files as a cache key.
There may be situations when you need to customize an existing node module or move a part of your application as a reusable module. In this case, you would want your local module to be used without any modifications and be rebuilt, should it contain native code.
With automatic detection of native code – such modules will be rebuilt on Cloud Foundry and cached, based on their contents for your next push.
More informative logging
In addition to these node improvements, you can now see a detailed log of what’s going on in log files. You can get log messages by running:
vmc logs application-name
We can see if npm support is enabled (npm-shrinkwrap.json was provided) and which node version we are using:
Installing dependencies. Node version 0.6.8
For each node module we can see its installation status:
Installing email@example.com from local path
In case of a failure we can see an error message and/or npm error output.:
Failed installing firstname.lastname@example.org: Node version requirement >= 0.6.0 is not compatible with the current node version 0.4.12
Modules using node-gyp for the installation process are now supported on CloudFoundry.com for node08 runtime. For node06 and node04 runtimes, Cloud Foundry falls back to node-waf if the module provides the wscript file.
Another recent improvement is that we also support git URLs in npm-shrinkwrap.json. They can be specified in “from” or “version” fields according to npm requirements and both methods are supported. We have a separate cache for git modules and they also get compiled on Cloud Foundry if they have native extensions.
In the previous blog post on auto-reconfiguration we used a Node app, “calipso”, and performed additional steps for npm support. Let’s see how pushing calipso works now.
First, we clone calipso source from github:
$ git clone git://github.com/cliftonc/calipso.git
Then, we install node modules and lock them down.
$ npm install $ npm shrinkwrap
Now, we can push our application.
$ vmc push calipso-app --runtime=node08
As we push we add mongodb service and set memory to 256M.
Would you like to deploy from the current directory? [Yn]: Detected a Node.js Application, is this correct? [Yn]: Application Deployed URL [calipso-app.cloudfoundry.com]: Memory reservation (128M, 256M, 512M, 1G, 2G) [64M]: 256M How many instances? : Bind existing services to 'calipso-app'? [yN]: Create services to bind to 'calipso-app'? [yN]: y 1: blob 2: mongodb 3: mysql 4: postgresql 5: rabbitmq 6: redis What kind of service?: 2 Specify the name of the service [mongodb-62f4d]: Create another? [yN]: Would you like to save this configuration? [yN]: Creating Application: OK Creating Service [mongodb-62f4d]: OK Binding Service [mongodb-62f4d]: OK Uploading Application: Checking for available resources: OK Processing resources: OK Packing application: OK Uploading (82K): OK Push Status: OK Staging Application 'calipso-app': OK Starting Application 'calipso-app': OK
That’s it! We didn’t need to configure our application at all. In addition, notice that staging process was faster and the preparation was effortless. When we look at the logs we can see how everything went. Try it and see how easy it is to manage your dependencies in Node.js applications now.
- Maria Shaldibina
The Cloud Foundry Team