197 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
			
		
		
	
	
			197 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
| <section xmlns="http://docbook.org/ns/docbook"
 | |
|          xmlns:xlink="http://www.w3.org/1999/xlink"
 | |
|          xml:id="sec-bower">
 | |
|  <title>Bower</title>
 | |
| 
 | |
|  <para>
 | |
|   <link xlink:href="http://bower.io">Bower</link> is a package manager for web site front-end components. Bower packages (comprising of build artefacts and sometimes sources) are stored in <command>git</command> repositories, typically on Github. The package registry is run by the Bower team with package metadata coming from the <filename>bower.json</filename> file within each package.
 | |
|  </para>
 | |
| 
 | |
|  <para>
 | |
|   The end result of running Bower is a <filename>bower_components</filename> directory which can be included in the web app's build process.
 | |
|  </para>
 | |
| 
 | |
|  <para>
 | |
|   Bower can be run interactively, by installing <varname>nodePackages.bower</varname>. More interestingly, the Bower components can be declared in a Nix derivation, with the help of <varname>nodePackages.bower2nix</varname>.
 | |
|  </para>
 | |
| 
 | |
|  <section xml:id="ssec-bower2nix-usage">
 | |
|   <title><command>bower2nix</command> usage</title>
 | |
| 
 | |
|   <para>
 | |
|    Suppose you have a <filename>bower.json</filename> with the following contents:
 | |
|    <example xml:id="ex-bowerJson">
 | |
|     <title><filename>bower.json</filename></title>
 | |
| <programlisting language="json">
 | |
| <![CDATA[{
 | |
|   "name": "my-web-app",
 | |
|   "dependencies": {
 | |
|     "angular": "~1.5.0",
 | |
|     "bootstrap": "~3.3.6"
 | |
|   }
 | |
| }]]>
 | |
| </programlisting>
 | |
|    </example>
 | |
|   </para>
 | |
| 
 | |
|   <para>
 | |
|    Running <command>bower2nix</command> will produce something like the following output:
 | |
| <programlisting language="nix">
 | |
| <![CDATA[{ fetchbower, buildEnv }:
 | |
| buildEnv { name = "bower-env"; ignoreCollisions = true; paths = [
 | |
|   (fetchbower "angular" "1.5.3" "~1.5.0" "1749xb0firxdra4rzadm4q9x90v6pzkbd7xmcyjk6qfza09ykk9y")
 | |
|   (fetchbower "bootstrap" "3.3.6" "~3.3.6" "1vvqlpbfcy0k5pncfjaiskj3y6scwifxygfqnw393sjfxiviwmbv")
 | |
|   (fetchbower "jquery" "2.2.2" "1.9.1 - 2" "10sp5h98sqwk90y4k6hbdviwqzvzwqf47r3r51pakch5ii2y7js1")
 | |
| ]; }]]>
 | |
| </programlisting>
 | |
|   </para>
 | |
| 
 | |
|   <para>
 | |
|    Using the <command>bower2nix</command> command line arguments, the output can be redirected to a file. A name like <filename>bower-packages.nix</filename> would be fine.
 | |
|   </para>
 | |
| 
 | |
|   <para>
 | |
|    The 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 <varname>buildBowerComponents</varname> is useful.
 | |
|   </para>
 | |
|  </section>
 | |
| 
 | |
|  <section xml:id="ssec-build-bower-components">
 | |
|   <title><varname>buildBowerComponents</varname> function</title>
 | |
| 
 | |
|   <para>
 | |
|    The function is implemented in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/bower-modules/generic/default.nix"> <filename>pkgs/development/bower-modules/generic/default.nix</filename></link>. Example usage:
 | |
|    <example xml:id="ex-buildBowerComponents">
 | |
|     <title>buildBowerComponents</title>
 | |
| <programlisting language="nix">
 | |
| bowerComponents = buildBowerComponents {
 | |
|   name = "my-web-app";
 | |
|   generated = ./bower-packages.nix; <co xml:id="ex-buildBowerComponents-1" />
 | |
|   src = myWebApp; <co xml:id="ex-buildBowerComponents-2" />
 | |
| };
 | |
| </programlisting>
 | |
|    </example>
 | |
|   </para>
 | |
| 
 | |
|   <para>
 | |
|    In <xref linkend="ex-buildBowerComponents" />, the following arguments are of special significance to the function:
 | |
|    <calloutlist>
 | |
|     <callout arearefs="ex-buildBowerComponents-1">
 | |
|      <para>
 | |
|       <varname>generated</varname> specifies the file which was created by <command>bower2nix</command>.
 | |
|      </para>
 | |
|     </callout>
 | |
|     <callout arearefs="ex-buildBowerComponents-2">
 | |
|      <para>
 | |
|       <varname>src</varname> is your project's sources. It needs to contain a <filename>bower.json</filename> file.
 | |
|      </para>
 | |
|     </callout>
 | |
|    </calloutlist>
 | |
|   </para>
 | |
| 
 | |
|   <para>
 | |
|    <varname>buildBowerComponents</varname> will run Bower to link together the output of <command>bower2nix</command>, resulting in a <filename>bower_components</filename> directory which can be used.
 | |
|   </para>
 | |
| 
 | |
|   <para>
 | |
|    Here is an example of a web frontend build process using <command>gulp</command>. You might use <command>grunt</command>, or anything else.
 | |
|   </para>
 | |
| 
 | |
|   <example xml:id="ex-bowerGulpFile">
 | |
|    <title>Example build script (<filename>gulpfile.js</filename>)</title>
 | |
| <programlisting language="javascript">
 | |
| <![CDATA[var gulp = require('gulp');
 | |
| 
 | |
| gulp.task('default', [], function () {
 | |
|   gulp.start('build');
 | |
| });
 | |
| 
 | |
| gulp.task('build', [], function () {
 | |
|   console.log("Just a dummy gulp build");
 | |
|   gulp
 | |
|     .src(["./bower_components/**/*"])
 | |
|     .pipe(gulp.dest("./gulpdist/"));
 | |
| });]]>
 | |
| </programlisting>
 | |
|   </example>
 | |
| 
 | |
|   <example xml:id="ex-buildBowerComponentsDefaultNix">
 | |
|    <title>Full example — <filename>default.nix</filename></title>
 | |
| <programlisting language="nix">
 | |
| { myWebApp ? { outPath = ./.; name = "myWebApp"; }
 | |
| , pkgs ? import <nixpkgs> {}
 | |
| }:
 | |
| 
 | |
| pkgs.stdenv.mkDerivation {
 | |
|   name = "my-web-app-frontend";
 | |
|   src = myWebApp;
 | |
| 
 | |
|   buildInputs = [ pkgs.nodePackages.gulp ];
 | |
| 
 | |
|   bowerComponents = pkgs.buildBowerComponents { <co xml:id="ex-buildBowerComponentsDefault-1" />
 | |
|     name = "my-web-app";
 | |
|     generated = ./bower-packages.nix;
 | |
|     src = myWebApp;
 | |
|   };
 | |
| 
 | |
|   buildPhase = ''
 | |
|     cp --reflink=auto --no-preserve=mode -R $bowerComponents/bower_components . <co xml:id="ex-buildBowerComponentsDefault-2" />
 | |
|     export HOME=$PWD <co xml:id="ex-buildBowerComponentsDefault-3" />
 | |
|     ${pkgs.nodePackages.gulp}/bin/gulp build <co xml:id="ex-buildBowerComponentsDefault-4" />
 | |
|   '';
 | |
| 
 | |
|   installPhase = "mv gulpdist $out";
 | |
| }
 | |
| </programlisting>
 | |
|   </example>
 | |
| 
 | |
|   <para>
 | |
|    A few notes about <xref linkend="ex-buildBowerComponentsDefaultNix" />:
 | |
|    <calloutlist>
 | |
|     <callout arearefs="ex-buildBowerComponentsDefault-1">
 | |
|      <para>
 | |
|       The result of <varname>buildBowerComponents</varname> is an input to the frontend build.
 | |
|      </para>
 | |
|     </callout>
 | |
|     <callout arearefs="ex-buildBowerComponentsDefault-2">
 | |
|      <para>
 | |
|       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.
 | |
|      </para>
 | |
|     </callout>
 | |
|     <callout arearefs="ex-buildBowerComponentsDefault-3">
 | |
|      <para>
 | |
|       <command>gulp</command> requires <varname>HOME</varname> to refer to a writeable directory.
 | |
|      </para>
 | |
|     </callout>
 | |
|     <callout arearefs="ex-buildBowerComponentsDefault-4">
 | |
|      <para>
 | |
|       The actual build command. Other tools could be used.
 | |
|      </para>
 | |
|     </callout>
 | |
|    </calloutlist>
 | |
|   </para>
 | |
|  </section>
 | |
| 
 | |
|  <section xml:id="ssec-bower2nix-troubleshooting">
 | |
|   <title>Troubleshooting</title>
 | |
| 
 | |
|   <variablelist>
 | |
|    <varlistentry>
 | |
|     <term>
 | |
|      <literal>ENOCACHE</literal> errors from <varname>buildBowerComponents</varname>
 | |
|     </term>
 | |
|     <listitem>
 | |
|      <para>
 | |
|       This means that Bower was looking for a package version which doesn't exist in the generated <filename>bower-packages.nix</filename>.
 | |
|      </para>
 | |
|      <para>
 | |
|       If <filename>bower.json</filename> has been updated, then run <command>bower2nix</command> again.
 | |
|      </para>
 | |
|      <para>
 | |
|       It could also be a bug in <command>bower2nix</command> or <command>fetchbower</command>. If possible, try reformulating the version specification in <filename>bower.json</filename>.
 | |
|      </para>
 | |
|     </listitem>
 | |
|    </varlistentry>
 | |
|   </variablelist>
 | |
|  </section>
 | |
| </section>
 | 
