Our frontend is written in Elm and our deployments are done with Nix.
There are many benefits to using Nix for packaging: like reproducible installation with binaries, being able to diff for changes, rollback support, etc, with a single generic tool.
We benefit most once the whole deployment is Nixified, which is what we’ve done to our frontend in last December.
History
Back in November 2016 I’ve written down some ideas on how elm2nix could work. In December 2017 the first prototype of elm2nix was born, but it required a fork of the Elm compiler to gathering your project’s dependencies. Elm 0.19 came out with pinning for all dependencies, making it feasible for other packaging software to build Elm projects.
Installation and usage
Today we’re releasing elm2nix 0.1 and it’s already available in nixpkgs unstable and stable channels. The easiest way to install it is:
# install Nix
$ curl https://nixos.org/nix/install | sh
# activate Nix environment
$ source ~/.nix-profile/etc/profile.d/nix.sh
# install elm2nix binary
$ nix-env -i elm2nix
Given your current directory with an Elm 0.19 project, here are three commands to get Elm project build with Nix.
First, we need to generate a Nix file with metadata about dependencies:
$ elm2nix convert > elm-srcs.nix
Second, since Elm 0.19 packaging maintains a snapshot of http://package.elm-lang.org
$ elm2nix snapshot > versions.dat
And last, we generate a Nix expression by template, which ties everything together:
$ elm2nix init > default.nix
By default, the template will use just plain elm-make
to compile your project.
To build using Nix and see the generated output in Chromium:
$ nix-build
$ chromium ./result/Main.html
What could be improved in Elm
You may notice that elm2nix convert
output includes sha256 hashes. Nix will require hashes
for anything that’s fetched from the internet. Elm package index does provide an
endpoint with
hashes, but then Nix needs to know what’s the hash of the endpoint response.
To address this issue it would be ideal if there would be elm.lock
file or similar
with all dependencies pinned including their hashes - then Nix would have everything
available locally. Other package managers for various languages are slowly going towards
outputing metadata file that explains the whole build process. This can be considered an API
between build planning and the actual builder.
Another minor issue comes from versions.dat
. Ideally instead of committing to git repository
a few megabytes of serialized JSON, one would be able to point to an url that would
present binary file pinned at some specific time - allowing it to always be verifiable
with upfront known hash.
What could be improved in Nix
Nix expression generated by elm2nix init
could be upstreamed to nixpkgs or another Nix
repository. This would allow for small footprint in an application and stable documentation.
Default expression might not be enough for everyone, as you can use Parcel, Webpack or any other asset management tool for building the project. There’s room for all common environments.
Closing thoughts
Stay tuned for another post on how to develop Elm applications with Parcel and Nix.
Since you’re here, we’re building next-generation CI and binary caching services, take a look at Hercules CI and Cachix.