For a while, it seemed as though the industry would standardize on using npm exclusively for Node.js packages and Bower for packages written for the browser. We initially designed Roost to reflect this trend.
The npm team recently voiced their interest in supporting both use cases, and through guides on publishing jQuery plugins to last week’s beta release of npm 3, they’ve since been making strides toward that goal. I’d like to talk about why we decided to embrace this change and use npm in isolation for Roost.
To begin, here’s an overview of how we demonstrated using npm in conjunction with Bower to build a web application:
postinstallnpm script to install Bower dependencies automatically following the successful installation of npm modules
node_modules/directory was ignored by the project’s version control system. While building the application, we would update this configuration to also include the
npmcommand-line tool and how to use the
package.jsonfile for the project’s Node.js dependencies and a
bower.jsonfile for the project’s browser dependencies
This mimicked the setup we had been using for consulting projects, and it was certainly serviceable. I say “serviceable” because we recognized some pain points about that approach.
Every tool we use introduces a new concept in the workflow. As the number of concepts grows, so too does the cognitive load placed on the developer. While we could optimize our workflow for “smallest number of tools,” we hold a conflicting belief in the Unix philosophy (that is: every tool should do one thing and do it well). This value normally trumps our concerns for cognitive load, but it doesn’t exactly apply to using both Bower and npm. These tools do the same thing (albeit in slightly different ways). That makes the extra conceptual overhead hard to justify, especially in the context of an educational experience like Roost.
This cognitive load is most apparent in those cases where the core semantics of
the tools differ. For example npm saves packages using the
while Bower saves packages using the
In order to use both tools concurrently, users need to understand this subtle
distinction and keep it in mind whenever they install new dependencies.
Besides being harder to conceptualize, a “dual package manager” workflow is just plain awkward. Initial installation requires steps for both tools, and this of course increases the amount of documentation needed. (We experimented with alternate installation procedures to avoid this, but we’re not comfortable recommending approaches that the projects don’t themselves endorse.)
Difficulties persist beyond the project’s initial set up. Packaging information
must be managed across two distinct files. This makes it harder to get an
overview of a project’s third-party dependencies, and it forces developers to
maintain duplication in common fields like
version. When the
time comes to update, developers have to run two commands to get the latest
version of their dependencies (or wire the tools together in non-obvious ways).
As you might expect, no one walked away from Roost San Diego or Roost Chicago saying, “I was inspired by the serviceable approach to package management!” So when the npm team announced its plans to shoulder more responsibilities, we were all ears.
As a testament to both tools, the change itself couldn’t have been easier. We simply moved some dependencies from one manifest file to another, updated a few paths in our RequireJS configuration, and we were done! As we hoped, this allowed us to streamline the course content that dealt with package management. Here’s an overview:
node_modules/when initializing the project
We think this represents a much stronger workflow, and we hope it will make the content even more approachable.
This approach allows us to address the important aspects of third-party dependency management without getting weighed down by implementation details. That said, there are some realities that may make it inappropriate for wider use today.
Even if current-day realities make this issue a little less cut-and-dry, we’re convinced this approach to be both more progressive and more conducive to an educational setting. We hope you agree!