Hi!
I’m learning Nix and trying to apply it to web development. At this stage I got a working setup with Node2Nix and Parcel. The whole code is here. The problem is that it’s very slow to enter the environment (about 50 s, and it’s a very bare bone app). Below I describe how I set things up hoping for an advice.
First I use node2nix
to generate Nix expressions from NPM’s lock file, like this:
node2nix \
--development \
--lock package-lock.json \
--composition node-dependencies.nix
Then I call nix build
with the following expression (in default.nix
file) to build the dist/
directory with final HTML, JS etc. and install it to the Nix store:
with import <nixpkgs> {};
let
nodeDependencies = (
pkgs.callPackage ./node-dependencies.nix {}
).shell.nodeDependencies;
in
pkgs.stdenv.mkDerivation {
name = "nix-for-web-development-playground";
src = ./.;
buildInputs = [ pkgs.nodejs pkgs.utillinux nodeDependencies ];
buildPhase = "make dist";
inherit nodeDependencies;
}
The dist
target in the Makefile
is basically this:
ln -s $(nodeDependencies)/lib/node_modules ./node_modules
parcel build src/index.html
This works in principle. I can call:
nix build
npx serve result
and have the app served on http://localhost:5000/. I can also call nix-shell default.nix
to get a working development environment. This is great.
The main problem now is that booth commands take about 50s, even on subsequent executions without any changes to the code. I thought that after first build all it would take is to link the paths from Nix store and set some environment variables. But apparently there is a lot going on. In the build logs I see a lot of:
unpacking source archive /nix/store/[...].tgz
that seems to refer to Node dependencies. Then there is
pinpointing versions of dependencies...
That takes quite long. Then
patching script interpreter paths in .
with a lot of
interpreter directive changed from "/usr/bin/env node" to "/nix/store/jq3lr9b5kzhxn3yjrgxpab543y8nx9dj-nodejs-12.18.4/bin/node"
then a lot of
Adding metadata fields to: node_modules/[...]/package.json
Then running postinstall
hooks on some modules.
Then some shrinking, patching and rewriting before the final build is performed. Here is a complete output from nix-shell default.nix
(about 2300 lines).
I understand why most of these steps are needed, but why does it have to happen every time I enter the environment? Can I avoid it?
Thank you and please consider that I’m early in my learning process.