mkogg.py: Fix 'self.get_mp4_metadata(self, source)'
[blog.git] / posts / Node.mdwn
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
6 how it works.
7
8 Start off by installing [npm][], the Node package manager.  On Gentoo,
9 that's:
10
11     # USE=npm emerge -av net-libs/nodejs
12
13 [Configure npm][npm-config] to make ["global"
14 installs][npm-folders-prefix] in your personal space:
15
16     # npm config set prefix ~/.local/
17
18 Install the [Grunt][] command line interface for building
19 [Bootstrap][]:
20
21     $ npm install -g grunt-cli
22
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]]).
26
27 Clone Boostrap and [install it's
28 dependencies][bootstrap-dependencies]:
29
30     $ git clone git://github.com/twbs/bootstrap.git
31     $ cd bootstrap
32     $ npm install
33
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:
39
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
46
47 Sometimes the redundancy is due to different version requirements, but
48 sometimes the redundancy is just redundant :p.  Let's look with [npm
49 ls][npm-ls].
50
51     $ npm ls graceful-fs
52     bootstrap@3.0.0 /home/wking/src/bootstrap
53     ├─┬ grunt@0.4.1
54     │ ├─┬ glob@3.1.21
55     │ │ └── graceful-fs@1.2.3
56     │ └─┬ rimraf@2.0.3
57     │   └── graceful-fs@1.1.14
58     ├─┬ grunt-contrib-clean@0.5.0
59     │ └─┬ rimraf@2.2.2
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
64     │     └─┬ rimraf@2.0.3
65     │       └── graceful-fs@1.1.14
66     └─┬ grunt-contrib-watch@0.5.3
67       └─┬ gaze@0.4.1
68         └─┬ globule@0.1.0
69           └─┬ glob@3.1.21
70             └── graceful-fs@1.2.3
71
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]:
76
77     $ rm -rf node_modules
78     $ npm install graceful-fs@1.1.14
79     $ npm install
80     $ npm ls graceful-fs
81     bootstrap@3.0.0 /home/wking/src/bootstrap
82     ├── graceful-fs@1.1.14  extraneous
83     ├─┬ grunt@0.4.1
84     │ └─┬ glob@3.1.21
85     │   └── graceful-fs@1.2.3 
86     ├─┬ grunt-contrib-clean@0.5.0
87     │ └─┬ rimraf@2.2.2
88     │   └── graceful-fs@2.0.1 
89     └─┬ grunt-contrib-watch@0.5.3
90       └─┬ gaze@0.4.1
91         └─┬ globule@0.1.0
92           └─┬ glob@3.1.21
93             └── graceful-fs@1.2.3 
94
95 This is probably not worth the trouble.
96
97 Now that we have Grunt and the Bootstrap dependencies, we can build
98 the distributed libraries:
99
100     $ ~/src/node_modules/.bin/grunt dist
101     Running "clean:dist" (clean) task
102     Cleaning dist...OK
103
104     Running "recess:bootstrap" (recess) task
105     File "dist/css/bootstrap.css" created.
106
107     Running "recess:min" (recess) task
108     File "dist/css/bootstrap.min.css" created.
109     Original: 121876 bytes.
110     Minified: 99741 bytes.
111
112     Running "recess:theme" (recess) task
113     File "dist/css/bootstrap-theme.css" created.
114
115     Running "recess:theme_min" (recess) task
116     File "dist/css/bootstrap-theme.min.css" created.
117     Original: 18956 bytes.
118     Minified: 17003 bytes.
119
120     Running "copy:fonts" (copy) task
121     Copied 4 files
122
123     Running "concat:bootstrap" (concat) task
124     File "dist/js/bootstrap.js" created.
125
126     Running "uglify:bootstrap" (uglify) task
127     File "dist/js/bootstrap.min.js" created.
128     Original: 58543 bytes.
129     Minified: 27811 bytes.
130
131     Done, without errors.
132
133 Wohoo!
134
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:
138
139     $ ~/src/node_modules/.bin/grunt
140     …
141     Running "jekyll:docs" (jekyll) task
142     `jekyll build` was initiated.
143
144     Jekyll output:
145     Warning: Command failed: /bin/sh: jekyll: command not found
146      Use --force to continue.
147
148     Aborted due to warnings.
149
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.
153
154 [[!tag tags/programming]]
155 [[!tag tags/tools]]
156 [[!tag tags/web]]
157
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/