1 [Node][] is a server-side [JavaScript][] engine (i.e. it executes
2 JavaScript without using a browser). This means that JavaScript
3 developers can now develop tools in their native language, so it's not
4 a surprise that the [Bootstrap][] folks use [Grunt][] for their build
5 system. I'm new to the whole Node ecosystem, so here are my notes on
8 Start off by installing [npm][], the Node package manager. On Gentoo,
11 # USE=npm emerge -av net-libs/nodejs
13 [Configure npm][npm-config] to make ["global"
14 installs][npm-folders-prefix] in your personal space:
16 # npm config set prefix ~/.local/
18 Install the [Grunt][] command line interface for building
21 $ npm install -g grunt-cli
23 That installs the libraries under `~/.local/lib/node_modules` and
24 drops symlinks to binaries in `~/.local/bin` (which is [already in my
25 `PATH`][PATH] thanks to my [[dotfiles]]).
27 Clone Boostrap and [install it's
28 dependencies][bootstrap-dependencies]:
30 $ git clone git://github.com/twbs/bootstrap.git
34 This looks in the local [package.json][] to extract a list of
35 dependencies, and [installs each of them][npm-folders] under
36 [node_modules][]. Node likes to isolate its packages, so every
37 dependency for a given package is installed underneath that package.
38 This leads to some crazy nesting:
40 $ find node_modules/ -name graceful-fs
41 node_modules/grunt/node_modules/glob/node_modules/graceful-fs
42 node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs
43 node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs
44 node_modules/grunt-contrib-qunit/node_modules/grunt-lib-phantomjs/node_modules/phantomjs/node_modules/rimraf/node_modules/graceful-fs
45 node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs
47 Sometimes the redundancy is due to different version requirements, but
48 sometimes the redundancy is just redundant :p. Let's look with [npm
52 bootstrap@3.0.0 /home/wking/src/bootstrap
55 │ │ └── graceful-fs@1.2.3
57 │ └── graceful-fs@1.1.14
58 ├─┬ grunt-contrib-clean@0.5.0
60 │ └── graceful-fs@2.0.1
61 ├─┬ grunt-contrib-qunit@0.2.2
62 │ └─┬ grunt-lib-phantomjs@0.3.1
63 │ └─┬ phantomjs@1.9.2-1
65 │ └── graceful-fs@1.1.14
66 └─┬ grunt-contrib-watch@0.5.3
72 Regardless of on-disk duplication, Node [caches modules][caching] so a
73 given module only loads once. If it really bothers you, you can
74 [avoid some duplicates by installing duplicated packages higher up in
75 the local tree][npm-folders-nesting]:
78 $ npm install graceful-fs@1.1.14
81 bootstrap@3.0.0 /home/wking/src/bootstrap
82 ├── graceful-fs@1.1.14 extraneous
85 │ └── graceful-fs@1.2.3
86 ├─┬ grunt-contrib-clean@0.5.0
88 │ └── graceful-fs@2.0.1
89 └─┬ grunt-contrib-watch@0.5.3
95 This is probably not worth the trouble.
97 Now that we have Grunt and the Bootstrap dependencies, we can build
98 the distributed libraries:
100 $ ~/src/node_modules/.bin/grunt dist
101 Running "clean:dist" (clean) task
104 Running "recess:bootstrap" (recess) task
105 File "dist/css/bootstrap.css" created.
107 Running "recess:min" (recess) task
108 File "dist/css/bootstrap.min.css" created.
109 Original: 121876 bytes.
110 Minified: 99741 bytes.
112 Running "recess:theme" (recess) task
113 File "dist/css/bootstrap-theme.css" created.
115 Running "recess:theme_min" (recess) task
116 File "dist/css/bootstrap-theme.min.css" created.
117 Original: 18956 bytes.
118 Minified: 17003 bytes.
120 Running "copy:fonts" (copy) task
123 Running "concat:bootstrap" (concat) task
124 File "dist/js/bootstrap.js" created.
126 Running "uglify:bootstrap" (uglify) task
127 File "dist/js/bootstrap.min.js" created.
128 Original: 58543 bytes.
129 Minified: 27811 bytes.
131 Done, without errors.
135 Unfortunately, like all [language-specific][pypi] [packing][gem]
136 [systems][cpan], npm has trouble installing packages that aren't
137 written in its native language. This means you get things like:
139 $ ~/src/node_modules/.bin/grunt
141 Running "jekyll:docs" (jekyll) task
142 `jekyll build` was initiated.
145 Warning: Command failed: /bin/sh: jekyll: command not found
146 Use --force to continue.
148 Aborted due to warnings.
150 Once everybody wises up and starts writing packages for [[Gentoo
151 Prefix|Gentoo_Prefix_overlay]], we can stop worrying about
152 installation and get back to work developing :p.
154 [[!tag tags/programming]]
158 [Node]: http://nodejs.org/
159 [JavaScript]: http://en.wikipedia.org/wiki/JavaScript
160 [Bootstrap]: http://getbootstrap.com/
161 [Grunt]: http://gruntjs.com/
162 [npm]: https://npmjs.org/
163 [npm-folders]: https://npmjs.org/doc/files/npm-folders.html
164 [npm-folders-prefix]: https://npmjs.org/doc/files/npm-folders.html#prefix-Configuration
165 [npm-folders-nesting]: https://npmjs.org/doc/files/npm-folders.html#Cycles-Conflicts-and-Folder-Parsimony
166 [npm-config]: https://npmjs.org/doc/config.html
167 [PATH]: http://git.tremily.us/?p=dotfiles-public.git;a=blob;f=src/.bash_profile;hb=HEAD
168 [bootstrap-dependencies]: https://github.com/twbs/bootstrap/blob/master/README.md#install-grunt
169 [package.json]: https://npmjs.org/doc/json.html
170 [node_modules]: http://nodejs.org/api/modules.html#modules_loading_from_node_modules_folders
171 [npm-ls]: https://npmjs.org/doc/cli/npm-ls.html
172 [caching]: http://nodejs.org/api/modules.html#modules_caching
173 [pypi]: https://pypi.python.org/pypi
174 [gem]: http://rubygems.org/
175 [cpan]: http://www.cpan.org/