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