I wasted days of my life trying to figure out how to create a solid deployment of node.js applications across heterogenous environments. Maybe I can spare you some of the trouble.
To me, deployable means that the application should be
- able to be rolled out, with 100% confidence across development, quality assurance, and production environments, with no modification to the codebase.
- Require only a minimal subset of pre-installed libraries. In the case of node.js, this means each environments should only guarantee the correct node version and npm version. Nothing else.
- The application can be monitored for uptime, and can be restarted like any other unix service.
So, I have written a node.js application. I have provided a package.json file. I run
npm install in the application’s folder. All the dependencies are installed correctly and my application runs. Great!
I then git add the application to the repository. And then I go to another server and do a git pull of my current branch. I try to start my application, and it fails, due to missing libraries. Why?
The problem is that npm-installed modules include instructions to the developer’s source code management tool. Instructions such as svn ignore, or git ignore. The files are included in their code when they export their modules to the archive.
So if you are unlucky enough to be using the same source code management tool as the module developer, you might be running afoul of the instructions the developer gave to his or her own repository.
So, as a git user, when I install my node modules and then issue the git add command, the downloaded modules are not allowing git to add their dependencies, because of the included .gitignore files telling git to ignore the node_modules directories. Thus, the application works locally, but not when you try to pull into another environment.
Developers need to ignore their own dependencies during development and packaging. This is appropriate. But they should also be removing their source code management tool’s helper file before they share their code.
That, however, is not going to happen, so it’s up to us to resolve.
So what I do now before adding and committing new code in a node module is this:
for f in ` find . -type f -name '.gitignore'`; do
sed -i'' -e '/^node_modules/ d' "$f"
which removes all the references in the .gitignore instructions for node_modules directories.
Then, when I git add, *all* the npm installed code gets added to the repo, not just the top-level dependencies. Pulling the code into another environment now retrieves all the dependencies, even three or four levels down.
I will follow up with some suggestions covering the other points I made about making a node.js app deployable.