at 18.03-beta 7.4 kB view raw
1<section xmlns="http://docbook.org/ns/docbook" 2 xmlns:xlink="http://www.w3.org/1999/xlink" 3 xml:id="sec-bower"> 4 5<title>Bower</title> 6 7<para> 8 <link xlink:href="http://bower.io">Bower</link> is a package manager 9 for web site front-end components. Bower packages (comprising of 10 build artefacts and sometimes sources) are stored in 11 <command>git</command> repositories, typically on Github. The 12 package registry is run by the Bower team with package metadata 13 coming from the <filename>bower.json</filename> file within each 14 package. 15</para> 16 17<para> 18 The end result of running Bower is a 19 <filename>bower_components</filename> directory which can be included 20 in the web app's build process. 21</para> 22 23<para> 24 Bower can be run interactively, by installing 25 <varname>nodePackages.bower</varname>. More interestingly, the Bower 26 components can be declared in a Nix derivation, with the help of 27 <varname>nodePackages.bower2nix</varname>. 28</para> 29 30<section xml:id="ssec-bower2nix-usage"> 31 <title><command>bower2nix</command> usage</title> 32 33<para> 34 Suppose you have a <filename>bower.json</filename> with the following contents: 35 36 37<example xml:id="ex-bowerJson"><title><filename>bower.json</filename></title> 38<programlisting language="json"> 39<![CDATA[{ 40 "name": "my-web-app", 41 "dependencies": { 42 "angular": "~1.5.0", 43 "bootstrap": "~3.3.6" 44 } 45}]]> 46</programlisting> 47</example> 48</para> 49 50 51<para> 52 Running <command>bower2nix</command> will produce something like the 53 following output: 54 55<programlisting language="nix"> 56<![CDATA[{ fetchbower, buildEnv }: 57buildEnv { name = "bower-env"; ignoreCollisions = true; paths = [ 58 (fetchbower "angular" "1.5.3" "~1.5.0" "1749xb0firxdra4rzadm4q9x90v6pzkbd7xmcyjk6qfza09ykk9y") 59 (fetchbower "bootstrap" "3.3.6" "~3.3.6" "1vvqlpbfcy0k5pncfjaiskj3y6scwifxygfqnw393sjfxiviwmbv") 60 (fetchbower "jquery" "2.2.2" "1.9.1 - 2" "10sp5h98sqwk90y4k6hbdviwqzvzwqf47r3r51pakch5ii2y7js1") 61]; }]]> 62</programlisting> 63</para> 64 65 66<para> 67 Using the <command>bower2nix</command> command line arguments, the 68 output can be redirected to a file. A name like 69 <filename>bower-packages.nix</filename> would be fine. 70</para> 71 72<para> 73 The resulting derivation is a union of all the downloaded Bower 74 packages (and their dependencies). To use it, they still need to be 75 linked together by Bower, which is where 76 <varname>buildBowerComponents</varname> is useful. 77</para> 78</section> 79 80<section xml:id="ssec-build-bower-components"><title><varname>buildBowerComponents</varname> function</title> 81 82 <para> 83 The function is implemented in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/bower-modules/generic/default.nix"> 84 <filename>pkgs/development/bower-modules/generic/default.nix</filename></link>. 85 Example usage: 86 87<example xml:id="ex-buildBowerComponents"><title>buildBowerComponents</title> 88<programlisting language="nix"> 89bowerComponents = buildBowerComponents { 90 name = "my-web-app"; 91 generated = ./bower-packages.nix; <co xml:id="ex-buildBowerComponents-1" /> 92 src = myWebApp; <co xml:id="ex-buildBowerComponents-2" /> 93}; 94</programlisting> 95</example> 96 </para> 97 98<para> 99In <xref linkend="ex-buildBowerComponents" />, the following arguments 100are of special significance to the function: 101 102<calloutlist> 103 <callout arearefs="ex-buildBowerComponents-1"> 104 <para> 105 <varname>generated</varname> specifies the file which was created by <command>bower2nix</command>. 106 </para> 107 </callout> 108 109 <callout arearefs="ex-buildBowerComponents-2"> 110 <para> 111 <varname>src</varname> is your project's sources. It needs to 112 contain a <filename>bower.json</filename> file. 113 </para> 114 </callout> 115</calloutlist> 116</para> 117 118<para> 119 <varname>buildBowerComponents</varname> will run Bower to link 120 together the output of <command>bower2nix</command>, resulting in a 121 <filename>bower_components</filename> directory which can be used. 122</para> 123 124<para> 125 Here is an example of a web frontend build process using 126 <command>gulp</command>. You might use <command>grunt</command>, or 127 anything else. 128</para> 129 130<example xml:id="ex-bowerGulpFile"><title>Example build script (<filename>gulpfile.js</filename>)</title> 131<programlisting language="javascript"> 132<![CDATA[var gulp = require('gulp'); 133 134gulp.task('default', [], function () { 135 gulp.start('build'); 136}); 137 138gulp.task('build', [], function () { 139 console.log("Just a dummy gulp build"); 140 gulp 141 .src(["./bower_components/**/*"]) 142 .pipe(gulp.dest("./gulpdist/")); 143});]]> 144</programlisting> 145</example> 146 147<example xml:id="ex-buildBowerComponentsDefaultNix"> 148 <title>Full example — <filename>default.nix</filename></title> 149<programlisting language="nix"> 150{ myWebApp ? { outPath = ./.; name = "myWebApp"; } 151, pkgs ? import &lt;nixpkgs&gt; {} 152}: 153 154pkgs.stdenv.mkDerivation { 155 name = "my-web-app-frontend"; 156 src = myWebApp; 157 158 buildInputs = [ pkgs.nodePackages.gulp ]; 159 160 bowerComponents = pkgs.buildBowerComponents { <co xml:id="ex-buildBowerComponentsDefault-1" /> 161 name = "my-web-app"; 162 generated = ./bower-packages.nix; 163 src = myWebApp; 164 }; 165 166 buildPhase = '' 167 cp --reflink=auto --no-preserve=mode -R $bowerComponents/bower_components . <co xml:id="ex-buildBowerComponentsDefault-2" /> 168 export HOME=$PWD <co xml:id="ex-buildBowerComponentsDefault-3" /> 169 ${pkgs.nodePackages.gulp}/bin/gulp build <co xml:id="ex-buildBowerComponentsDefault-4" /> 170 ''; 171 172 installPhase = "mv gulpdist $out"; 173} 174</programlisting> 175</example> 176 177<para> 178A few notes about <xref linkend="ex-buildBowerComponentsDefaultNix" />: 179 180<calloutlist> 181 <callout arearefs="ex-buildBowerComponentsDefault-1"> 182 <para> 183 The result of <varname>buildBowerComponents</varname> is an 184 input to the frontend build. 185 </para> 186 </callout> 187 188 <callout arearefs="ex-buildBowerComponentsDefault-2"> 189 <para> 190 Whether to symlink or copy the 191 <filename>bower_components</filename> directory depends on the 192 build tool in use. In this case a copy is used to avoid 193 <command>gulp</command> silliness with permissions. 194 </para> 195 </callout> 196 197 <callout arearefs="ex-buildBowerComponentsDefault-3"> 198 <para> 199 <command>gulp</command> requires <varname>HOME</varname> to 200 refer to a writeable directory. 201 </para> 202 </callout> 203 204 <callout arearefs="ex-buildBowerComponentsDefault-4"> 205 <para> 206 The actual build command. Other tools could be used. 207 </para> 208 </callout> 209</calloutlist> 210</para> 211</section> 212 213<section xml:id="ssec-bower2nix-troubleshooting"> 214 <title>Troubleshooting</title> 215 216<variablelist> 217 218 <varlistentry> 219 <term> 220 <literal>ENOCACHE</literal> errors from 221 <varname>buildBowerComponents</varname> 222 </term> 223 <listitem> 224 <para> 225 This means that Bower was looking for a package version which 226 doesn't exist in the generated 227 <filename>bower-packages.nix</filename>. 228 </para> 229 <para> 230 If <filename>bower.json</filename> has been updated, then run 231 <command>bower2nix</command> again. 232 </para> 233 <para> 234 It could also be a bug in <command>bower2nix</command> or 235 <command>fetchbower</command>. If possible, try reformulating 236 the version specification in <filename>bower.json</filename>. 237 </para> 238 </listitem> 239 </varlistentry> 240</variablelist> 241 242</section> 243 244</section>