Migration to a static site: Experience with Metalsmith vs Gulp
I started this site using poet on top of node.js and express, mainly wanting to expand my node skills and use my free Azure credits I got as a Microsoft employee. Azure Websites, the Heroku-like PaaS had just launched (now called App Services). It was a nice experience.
So how to build it?
Why node.js is Awesome, Part 2: Package and Dependency Management
At the core of node is npm, the node package manager (which apparently npm doesn't stand for that). Having dependencies managed by a package system is huge. In Java and .NET, package managers have been added after the fact, if they are used at all. Often people end up checking in binaries that then makes the repository huge with information not pertinent to your product, which also results in binary merge conflicts. How do those get organized? A legacy codebase I work on has them scattered throughout 3 different locations, not to mention naming styles.
Npm standardizes this by having all the dependencies in a folder named node_modules which cannot be renamed and a package.json that must be comformant too, which then node understands when you
require something. No need to set classpaths or hint paths correctly.
This also heavily pushes people to have all their dependies locally. Its still possible to have a global module installed and require it without declaring it in your package.json (Maybe there is a way to prevent this via static analysis?) You can end up pulling assemblies from the GAC in .NET too, but still so many packages aren't installable via NuGet (I'm looking at you Azure SDK, which of course the Azure SDK for Node.js installs via npm) which means every developer and the build server(s) better have the same versions installed or someone will be wasting time getting stuff to build.
Dependencies are also a tree structure, not a graph. If two modules depend on the same module, they each get their own copy, so they can have their own versions. This is great given prototypical inheritance. If you want to be strict about the type of object you are working with,
instanceof will only be true if your version of the module created the object, not another version , due to the constructor functions not being a reference to the same object. If you want to be lenient, you can always duck type it.
Statically typed languages have a graph of dependencies, and if A and B depend on different versions of C, pain will ensue. I gave seen .NET developers waste hours tracking down mismatching versions of dependencies, even with the help of assembly binding redirects. I don't think Java has any answer for this.
Why node.js is Awesome, Part 1: The Single Responsibility Principle
My favorite thing about node.js and the npm community is something that can't easily be put on a spec sheet. It's adherance to the single responsiblity principle.
Take a look at some of the most depnended on npm modules - they're often very small, like mkdirp, which is simply
mkdir -p in node. glob matches files like a shell does. node-uuid just generates UUIDs.
Is there a bug in the module? The module is small enough and tested well that you can dive in and help out, and send the bug fix as a pull request on GitHub. Don't like the design of the module your using, or development died out? Swap it out with a different module, and wire it up to your loosely coupled system.
This is definately a change in culture, as though I didn't use Rails much, but that community likes it's big frameworks that do a lot of magic. Which is nice until you disagree with an aspect of that magic, or need to tweak it or swap it out with something else for this one scenario.
A great coworker of mine once told me "The key to complexity is composition", which I have experienced to be true.