Strider, our continuous deployment platform for node.js and Python, is in fact written in node.js and Python and it was the first project that we started testing and deploying via Strider. Yes, we are in fact continuously deploying Strider via Strider itself. It’s our own small attempt to bootstrap the Singularity. (Continuous deployment means that we automatically test after every commit, and then immediately deploy that code to production if the tests pass.)
So anyway. We use node.js for our web application server (along with backbone.js on the client), and the workers (which run the actual tests) are written in Python. While node.js is best known for its real-time capabilities with websockets, it is very easy at this point to build your entire web app in node.js. Node.js has a great package manager in npm and a strong ecosystem of modules. One of our biggest challenges was figuring out which modules would work best. Here’s what we chose:
Templating: Jade is the favored templating engine of the Express.js core team and it is also our favorite. After using jade for a while, it now actually pains me whenever I need to fully type out html. The amount of typing that jade eliminates dwarfs that involved in the recent (ongoing?) semicolon debate.
Auth: Everyauth integrates tightly with Express and provides excellent authentication and authorization support both internally and against a long list of external services. To date, we have only used it for internal auth and for oauth against github.
Database: We use MongoDB as our primary datastore. To connect to MongoDB, we use Mongoose as well as Mongoose-Auth for Everyauth/MongoDB integration. This combination has worked well although it is less than ideal that every data object comes out of the auth module.
Session Store: We use connect-mongo as our session store.
Control-Flow: Step has proven very useful in certain situations. For example, since MongoDB has limited joins within the db, on occasion we may need to execute one query, and then upon receiving the result, execute a sequence of additional queries to perform a ‘software join’. Step significantly simplified the code required for this flow.
Testing: We use a number of modules for testing, including mock-request for mocking req/res pairs, Sinon.JS for other stubs and mocks, sanboxed-module for dependency injection, and should.js for assertions. Niall’s recent blog post talks about the testing modules in a bit more depth, and in a future post we will walk through an example app that uses all of them.
Logging: We send our logs to loggly and store them locally. We patched console.log/debug/warn/error to go into Winston at equiv levels.
HTTP Request: Request is the gold standard HTTP client for node.
Password Hashing: Bcrypt of course.
Websockets: Everyone uses socket.io and for good reason.
String Validation: We use node-validator to validate email addresses and whatnot.
- Humane Dates is very helpful for more readable dates – “2 hours ago” or “5 days ago” instead of just the raw date.
- Nibbler encodes and decodes our invite codes to and from base32.
That’s it for us. Have a favorite node.js module that isn’t on our list? Let us know in the comments.