Nix is a tool that allows you to make reproducible development environments. I've started using it in all my Elm side projects and I've had a good experience with it thus far. To pique your curiosity I just wanted to share my simple setup that has been working quite well for me.
When I first started using Nix I used nix-shell
with a shell.nix
file but I've recently switched to Nix flakes which uses nix develop
with a flake.nix
file.
nix-shell
Here's an example shell.nix
taken from my elm-7guis web application.
let
pkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/7f256d7da238cb627ef189d56ed590739f42f13b.tar.gz") {};
in
pkgs.mkShell {
packages = [
pkgs.caddy
pkgs.elmPackages.elm
pkgs.elmPackages.elm-format
pkgs.elmPackages.elm-optimize-level-2
pkgs.elmPackages.elm-review
pkgs.elmPackages.elm-test
pkgs.nodejs_18
pkgs.shellcheck
];
shellHook =
''
export project="$PWD"
export build="$project/.build"
export PATH="$project/bin:$PATH"
'';
}
When I run nix-shell
at the root of the project it puts me in a Nix shell that contains, among other programs, caddy
and shellcheck
. Notice that in the shellHook
I add the project's shell scripts to the PATH
. So once I'm in the Nix shell I can, among other things:
- Serve the main application with Caddy using
serve
. - Serve the prototype with Caddy using
serve-prototype
. - Find any bugs in the shell scripts with ShellCheck using
check
.
In some projects I've wanted to use HTTPie to test APIs and jq to work with some JSON data. Nix has been really helpful in managing those dependencies that I can't easily get from npm.
nix develop
Here's an example flake.nix
taken from my elm-integer library.
{
description = "A developer shell for working on elm-integer.";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=23.11";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
devShells.default = pkgs.mkShell {
name = "elm-integer";
packages = with pkgs.elmPackages; [
elm
elm-doc-preview
elm-format
elm-optimize-level-2
elm-test
pkgs.caddy
pkgs.nodejs_20
pkgs.nodePackages.terser
pkgs.shellcheck
];
shellHook =
''
export project="$PWD"
export build="$project/.build"
export PATH="$project/bin:$PATH"
npm install --loglevel silent
'';
};
}
);
}
I enter the Nix shell by running nix develop
but the end result is similar to before, i.e. I get access to the dependencies you see listed in packages
.
Conclusion
Nix has a steep learning curve, it takes a while to learn to use and even longer to understand, and it may not be needed for every Elm project. However, I hope that the little taste of Nix that I've given you has piqued your interests.
BTW, feel free to use my shell.nix
or flake.nix
files and tweak them to suit your needs.
Happy Nixing!
Top comments (2)
Nice! I do the same with Guix. Natively supports Elm!
guix.gnu.org/manual/devel/en/html_...
Interesting, I hadn't heard of Guix before. How long have you been using it? Would you recommend it over Nix?