Coming from a Ruby and Rails background, we've always found very strange how nowadays most JavaScript libraries that require Node Packaged Modules recommend some dependencies to be installed globally one by one. As Ruby developers that always felt strange to us. We'll see how to use npm like we use Bundler.
It seems that every recent JavaScript project has one or more npm install -g
commands you should run to install some of the project's dependencies globally.
That is bad for READMEs that grow bigger and bigger, bad for setup
time because developers are forced to read much more instructions before being
able to work and bad for your computer because you pollute system directories
with development packages.
So we've come up with this question: why on earth should you be installing stuff
with npm install -g
when npm is perfectly capable of running like Bundler
does?
After years of hard work done by using the great tool that Bundler is, we don't like installing all those libraries globally. Conceptually we like projects and applications to be self-contained, standardized and easy to just pick up and play.
Basically this is the workflow every Rails developer knows and loves:
- install bundler with
gem install bundler
if not already installed; - download an application, typically via
git clone
; cd
inside the application and runbundle install
.
These three steps are usually everything that's required to have the
dependencies you need to start playing with the application (for example to
start exploring with rails console
). That also means that you can go from zero
to the application running without even reading the README.
The same workflow seems unapplicable if you read the documentation of most npm packages. As a team we're still very much experimenting with JavaScript so we tend to change tools and libraries very often; we're still looking for the workflow that works best for us. That means we could be using different tools for different projects. Probably many developers are in our same exact position.
So this is why we've been trying to reproduce with npm the workflow we love with Bundler. We found that it is actually possible and quite easy.
Setup
As an example we'll demonstrate how to prepare an application from scratch by using ember-cli a utility we've been really interested in since it came out. It's basically a set of tools and templates to work with ember.
If you take a look at the project's
Getting Started section you'll
see there are plenty of tools you have to install by using npm install -g
.
We'll do it differently.
First of all make sure you have npm installed. In addition to installing npm you
should add the local binaries folder to your $PATH
environment variable. Since
npm will use the local directory node_modules
to keep all your packages (the
binaries too), you need to have this:
PATH=./node_modules/.bin:$PATH
somewhere inside your ~/.zshrc
or ~/.bashrc
files.
Then create an empty folder which will host your project. From inside the
project's directory you can run all the npm install
commands without the -g
flag and those will be installed in the ./node_modules
path inside your
project. You should also exclude this directory from your version control system
as this directory will contain code you don't want in your repository.
To create an application with ember-cli
:
$ npm install ember-cli
$ ember init
$ npm install --save-dev phantomjs bower
This will generate everything and keep track of the dependecies of your app
inside the package.json
file. Think of it as your Gemfile
for JavaScript
applications. The --save-dev
flag will make sure npm changes package.json
to
reflect the dependecies you just installed.
To make sure developers don't fight with different versions of a dependency we
can add a Gemfile.lock
equivalent, like this:
$ npm shrinkwrap --dev
Npm will add a new npm-shrinkwrap.json
that keeps track of the exact
dependencies required to run your precious application (that you might want to
keep in your repository).
The --dev
option makes sure development dependencies are tracked as well as
production dependencies.
Using the npm-shrinkwrap.json
file also has some benefits in production
because it ensures you always have control of which versions will actually be
installed in the production environment (just like Bundler).
Have fun
The procedure for setting up an application might be slightly longer than that required by Bundler but, after doing this, the next developer working on the application can just run:
$ npm install
after downloading the application to get all the dependencies required to use the application smoothly.