2016-03-26 16:50:45 +00:00
<section xmlns= "http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="sec-bower">
2018-05-02 00:54:21 +01:00
<title > Bower</title>
<para >
2019-09-18 21:12:54 +01:00
<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.
2018-05-02 00:54:21 +01:00
</para>
<para >
2019-09-18 21:12:54 +01:00
The end result of running Bower is a <filename > bower_components</filename> directory which can be included in the web app's build process.
2018-05-02 00:54:21 +01:00
</para>
<para >
2019-09-18 21:12:54 +01:00
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> .
2018-05-02 00:54:21 +01:00
</para>
2016-03-26 16:50:45 +00:00
2018-05-02 00:54:21 +01:00
<section xml:id= "ssec-bower2nix-usage" >
2016-03-26 16:50:45 +00:00
<title > <command > bower2nix</command> usage</title>
2018-05-02 00:54:21 +01:00
<para >
2019-09-18 21:12:54 +01:00
Suppose you have a <filename > bower.json</filename> with the following contents:
2018-05-02 00:54:21 +01:00
<example xml:id= "ex-bowerJson" >
<title > <filename > bower.json</filename> </title>
2016-03-26 16:50:45 +00:00
<programlisting language= "json" >
< ![CDATA[{
"name": "my-web-app",
"dependencies": {
"angular": "~1.5.0",
"bootstrap": "~3.3.6"
}
}]]>
</programlisting>
2018-05-02 00:54:21 +01:00
</example>
</para>
2016-03-26 16:50:45 +00:00
2018-05-02 00:54:21 +01:00
<para >
2019-09-18 21:12:54 +01:00
Running <command > bower2nix</command> will produce something like the following output:
2016-03-26 16:50:45 +00:00
<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>
2018-05-02 00:54:21 +01:00
</para>
2016-03-26 16:50:45 +00:00
2018-05-02 00:54:21 +01:00
<para >
2019-09-18 21:12:54 +01:00
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.
2018-05-02 00:54:21 +01:00
</para>
2016-03-26 16:50:45 +00:00
2018-05-02 00:54:21 +01:00
<para >
2019-09-18 21:12:54 +01:00
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.
2018-05-02 00:54:21 +01:00
</para>
</section>
2016-03-26 16:50:45 +00:00
2018-05-02 00:54:21 +01:00
<section xml:id= "ssec-build-bower-components" >
<title > <varname > buildBowerComponents</varname> function</title>
2016-03-26 16:50:45 +00:00
<para >
2019-09-18 21:12:54 +01:00
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:
2018-05-02 00:54:21 +01:00
<example xml:id= "ex-buildBowerComponents" >
<title > buildBowerComponents</title>
2016-03-26 16:50:45 +00:00
<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>
2018-05-02 00:54:21 +01:00
</example>
2016-03-26 16:50:45 +00:00
</para>
2018-05-02 00:54:21 +01:00
<para >
2019-09-18 21:12:54 +01:00
In <xref linkend= "ex-buildBowerComponents" /> , the following arguments are of special significance to the function:
2018-05-02 00:54:21 +01:00
<calloutlist >
<callout arearefs= "ex-buildBowerComponents-1" >
<para >
2019-09-18 21:12:54 +01:00
<varname > generated</varname> specifies the file which was created by <command > bower2nix</command> .
2018-05-02 00:54:21 +01:00
</para>
</callout>
<callout arearefs= "ex-buildBowerComponents-2" >
<para >
2019-09-18 21:12:54 +01:00
<varname > src</varname> is your project's sources. It needs to contain a <filename > bower.json</filename> file.
2018-05-02 00:54:21 +01:00
</para>
</callout>
</calloutlist>
</para>
<para >
2019-09-18 21:12:54 +01:00
<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.
2018-05-02 00:54:21 +01:00
</para>
<para >
2019-09-18 21:12:54 +01:00
Here is an example of a web frontend build process using <command > gulp</command> . You might use <command > grunt</command> , or anything else.
2018-05-02 00:54:21 +01:00
</para>
<example xml:id= "ex-bowerGulpFile" >
<title > Example build script (<filename > gulpfile.js</filename> )</title>
2016-03-26 16:50:45 +00:00
<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>
2018-05-02 00:54:21 +01:00
</example>
2016-03-26 16:50:45 +00:00
2018-05-02 00:54:21 +01:00
<example xml:id= "ex-buildBowerComponentsDefaultNix" >
<title > Full example — <filename > default.nix</filename> </title>
2016-03-26 16:50:45 +00:00
<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>
2018-05-02 00:54:21 +01:00
</example>
<para >
A few notes about <xref linkend= "ex-buildBowerComponentsDefaultNix" /> :
<calloutlist >
<callout arearefs= "ex-buildBowerComponentsDefault-1" >
<para >
2019-09-18 21:12:54 +01:00
The result of <varname > buildBowerComponents</varname> is an input to the frontend build.
2018-05-02 00:54:21 +01:00
</para>
</callout>
<callout arearefs= "ex-buildBowerComponentsDefault-2" >
<para >
2019-09-18 21:12:54 +01:00
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.
2018-05-02 00:54:21 +01:00
</para>
</callout>
<callout arearefs= "ex-buildBowerComponentsDefault-3" >
<para >
2019-09-18 21:12:54 +01:00
<command > gulp</command> requires <varname > HOME</varname> to refer to a writeable directory.
2018-05-02 00:54:21 +01:00
</para>
</callout>
<callout arearefs= "ex-buildBowerComponentsDefault-4" >
<para >
2016-03-26 16:50:45 +00:00
The actual build command. Other tools could be used.
2018-05-02 00:54:21 +01:00
</para>
</callout>
</calloutlist>
</para>
</section>
2016-03-26 16:50:45 +00:00
2018-05-02 00:54:21 +01:00
<section xml:id= "ssec-bower2nix-troubleshooting" >
2016-03-26 16:50:45 +00:00
<title > Troubleshooting</title>
2018-05-02 00:54:21 +01:00
<variablelist >
<varlistentry >
2018-06-01 02:03:37 +01:00
<term >
<literal > ENOCACHE</literal> errors from <varname > buildBowerComponents</varname>
2016-03-26 16:50:45 +00:00
</term>
<listitem >
2018-05-02 00:54:21 +01:00
<para >
2019-09-18 21:12:54 +01:00
This means that Bower was looking for a package version which doesn't exist in the generated <filename > bower-packages.nix</filename> .
2018-05-02 00:54:21 +01:00
</para>
<para >
2019-09-18 21:12:54 +01:00
If <filename > bower.json</filename> has been updated, then run <command > bower2nix</command> again.
2018-05-02 00:54:21 +01:00
</para>
<para >
2019-09-18 21:12:54 +01:00
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> .
2018-05-02 00:54:21 +01:00
</para>
2016-03-26 16:50:45 +00:00
</listitem>
2018-05-02 00:54:21 +01:00
</varlistentry>
</variablelist>
</section>
2016-03-26 16:50:45 +00:00
</section>