[Node][] is a server-side [JavaScript][] engine (i.e. it executes JavaScript without using a browser). This means that JavaScript developers can now develop tools in their native language, so it's not a surprise that the [Bootstrap][] folks use [Grunt][] for their build system. I'm new to the whole Node ecosystem, so here are my notes on how it works. Start off by installing [npm][], the Node package manager. On Gentoo, that's: # USE=npm emerge -av net-libs/nodejs [Configure npm][npm-config] to make ["global" installs][npm-folders-prefix] in your personal space: # npm config set prefix ~/.local/ Install the [Grunt][] command line interface for building [Bootstrap][]: $ npm install -g grunt-cli That installs the libraries under `~/.local/lib/node_modules` and drops symlinks to binaries in `~/.local/bin` (which is [already in my `PATH`][PATH] thanks to my [[dotfiles]]). Clone Boostrap and [install it's dependencies][bootstrap-dependencies]: $ git clone git://github.com/twbs/bootstrap.git $ cd bootstrap $ npm install This looks in the local [package.json][] to extract a list of dependencies, and [installs each of them][npm-folders] under [node_modules][]. Node likes to isolate its packages, so every dependency for a given package is installed underneath that package. This leads to some crazy nesting: $ find node_modules/ -name graceful-fs node_modules/grunt/node_modules/glob/node_modules/graceful-fs node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs node_modules/grunt-contrib-qunit/node_modules/grunt-lib-phantomjs/node_modules/phantomjs/node_modules/rimraf/node_modules/graceful-fs node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs Sometimes the redundancy is due to different version requirements, but sometimes the redundancy is just redundant :p. Let's look with [npm ls][npm-ls]. $ npm ls graceful-fs bootstrap@3.0.0 /home/wking/src/bootstrap ├─┬ grunt@0.4.1 │ ├─┬ glob@3.1.21 │ │ └── graceful-fs@1.2.3 │ └─┬ rimraf@2.0.3 │ └── graceful-fs@1.1.14 ├─┬ grunt-contrib-clean@0.5.0 │ └─┬ rimraf@2.2.2 │ └── graceful-fs@2.0.1 ├─┬ grunt-contrib-qunit@0.2.2 │ └─┬ grunt-lib-phantomjs@0.3.1 │ └─┬ phantomjs@1.9.2-1 │ └─┬ rimraf@2.0.3 │ └── graceful-fs@1.1.14 └─┬ grunt-contrib-watch@0.5.3 └─┬ gaze@0.4.1 └─┬ globule@0.1.0 └─┬ glob@3.1.21 └── graceful-fs@1.2.3 Regardless of on-disk duplication, Node [caches modules][caching] so a given module only loads once. If it really bothers you, you can [avoid some duplicates by installing duplicated packages higher up in the local tree][npm-folders-nesting]: $ rm -rf node_modules $ npm install graceful-fs@1.1.14 $ npm install $ npm ls graceful-fs bootstrap@3.0.0 /home/wking/src/bootstrap ├── graceful-fs@1.1.14 extraneous ├─┬ grunt@0.4.1 │ └─┬ glob@3.1.21 │ └── graceful-fs@1.2.3 ├─┬ grunt-contrib-clean@0.5.0 │ └─┬ rimraf@2.2.2 │ └── graceful-fs@2.0.1 └─┬ grunt-contrib-watch@0.5.3 └─┬ gaze@0.4.1 └─┬ globule@0.1.0 └─┬ glob@3.1.21 └── graceful-fs@1.2.3 This is probably not worth the trouble. Now that we have Grunt and the Bootstrap dependencies, we can build the distributed libraries: $ ~/src/node_modules/.bin/grunt dist Running "clean:dist" (clean) task Cleaning dist...OK Running "recess:bootstrap" (recess) task File "dist/css/bootstrap.css" created. Running "recess:min" (recess) task File "dist/css/bootstrap.min.css" created. Original: 121876 bytes. Minified: 99741 bytes. Running "recess:theme" (recess) task File "dist/css/bootstrap-theme.css" created. Running "recess:theme_min" (recess) task File "dist/css/bootstrap-theme.min.css" created. Original: 18956 bytes. Minified: 17003 bytes. Running "copy:fonts" (copy) task Copied 4 files Running "concat:bootstrap" (concat) task File "dist/js/bootstrap.js" created. Running "uglify:bootstrap" (uglify) task File "dist/js/bootstrap.min.js" created. Original: 58543 bytes. Minified: 27811 bytes. Done, without errors. Wohoo! Unfortunately, like all [language-specific][pypi] [packing][gem] [systems][cpan], npm has trouble installing packages that aren't written in its native language. This means you get things like: $ ~/src/node_modules/.bin/grunt … Running "jekyll:docs" (jekyll) task `jekyll build` was initiated. Jekyll output: Warning: Command failed: /bin/sh: jekyll: command not found Use --force to continue. Aborted due to warnings. Once everybody wises up and starts writing packages for [[Gentoo Prefix|Gentoo_Prefix_overlay]], we can stop worrying about installation and get back to work developing :p. [[!tag tags/programming]] [[!tag tags/tools]] [[!tag tags/web]] [Node]: http://nodejs.org/ [JavaScript]: http://en.wikipedia.org/wiki/JavaScript [Bootstrap]: http://getbootstrap.com/ [Grunt]: http://gruntjs.com/ [npm]: https://npmjs.org/ [npm-folders]: https://npmjs.org/doc/files/npm-folders.html [npm-folders-prefix]: https://npmjs.org/doc/files/npm-folders.html#prefix-Configuration [npm-folders-nesting]: https://npmjs.org/doc/files/npm-folders.html#Cycles-Conflicts-and-Folder-Parsimony [npm-config]: https://npmjs.org/doc/config.html [PATH]: http://git.tremily.us/?p=dotfiles-public.git;a=blob;f=src/.bash_profile;hb=HEAD [bootstrap-dependencies]: https://github.com/twbs/bootstrap/blob/master/README.md#install-grunt [package.json]: https://npmjs.org/doc/json.html [node_modules]: http://nodejs.org/api/modules.html#modules_loading_from_node_modules_folders [npm-ls]: https://npmjs.org/doc/cli/npm-ls.html [caching]: http://nodejs.org/api/modules.html#modules_caching [pypi]: https://pypi.python.org/pypi [gem]: http://rubygems.org/ [cpan]: http://www.cpan.org/