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