- If you install a package that has periods in the attribute path, you'll need to wrap the subpath on the command line using escaped double quotation marks. For example, packages generated by the
node2nix
tool can have NPM package versions affixed to the attribute, depending on hownode2nix
is set up. Version^0.0.1-1
ofredux-devtools-cli
may be represented asnodeModules.redux-devtools-cli-^0.0.1-1
, which on the command line would be installed like so:npm -f '<nixpkgs>' -iA "nodeModules.\"redux-devtools-cli-^0.0.1-1\""
.
Let's say that you want to make some NPM packages available for your Nix environment (e.g., nix-shell
, home-manager
). Here are the main patterns that I've identified:
Any dependencies added to a standard package.json
will get pulled into your nix-shell if you use the shell derivation generated by node2nix
. To make this seamless, node2nix
generates a custom package containing just your NPM dependencies and makes the NPM modules contained within this package available to the shell via a shell hook. The shell hook in turn sets PATH
and NODE_PATH
to point to the appropriate NPM modules.
Pros:
- Arguably the cleanest approach, maintains maximum compatibility with a standard
package.json
.
Cons:
- Only works if you're using
nix-shell
and specifically the shell derivation generated bynode2nix
. For example, you can't expose NPM packages to your system environment by putting them inside thedependencies
field of a dummypackage.json
and then installing the generated package, because the dependencies are only exposed to the environment throughnode2nix
's shell derivation. - Since you have to use
node2nix
's shell derivation, it becomes a bit awkard to get non-NPM dependencies and tooling into the shell environment. You end up having to modify the shell derivation usingoverrideAttrs
and the like, which isn't a clean approach.node2nix
doesn't expose the various bits that go into the shell derivation in a modular way for you to build your own custom shells.
If you're trying to get NPM packages in any non-shell environment, create a package.json
with an array of your NPM packages
If you create a package.json
that consists of an array with your desired NPM packages, node2nix
will generate a set of Nix packages, one for each NPM package. You can then merge this set with the top-level nodePackages
Nixpkgs attribute in an overlay. For example:
# ~/.config/overlays/nodePackages.nix
self: super:
{
# ~/nix/nodePackages contains your generated default.nix, node-packages.nix,
# node-env.nix, and your source package.json.
nodePackages = super.nodePackages // super.callPackage ../../../nix/nodePackages {};
}
Pros:
- A fairly clean approach. Requires a non-standard
package.json
, but you can always name this something different likepackages-for-overlay.json
and use the-i
option. I.e.,node2nix -i packages-for-overlay.json
. - The only game in town if you want to expose NPM packages within your Nix environment without relying on NPM, Yarn, etc.
Cons:
- Unlike packages listed in the
dependencies
field of a standardpackage.json
,node2nix
builds every package installed this way from scratch usingnpm rebuild
on the sources instead of grabbing a pre-built version from NPM--which, to be fair, is The Nix Way™️ and maintains purity. On the other hand, it means that a lot of packages that you'd assume just work won't install without further configuration to make sure their build-time dependencies are in place (see below). - Because this is the only way currently to install NPM packages using
node2nix
in a non-shell environment, you have no choice but to build every such package from source, if this is your use case. There's no way around it when using standardnode2nix
without any hackery.
If you're trying to expose build-time tooling to build your NPM packages from scratch, create a supplement.json
Some NPM packages require tooling at build-time (e.g., TypeScript, Gulp). You can include these using a supplement.json
file that's an array with your tooling in it. Your tooling packages then get passed into the buildInputs
attribute of your target packages' derivations. Simply pass in supplement.json
using --suplement-input
: node2nix -i package.json --supplement-input supplement.json
.
Pros:
- Keeps build tooling separate from target packages.
- The tooling packages don't get added to the package set generated by
node2nix
that has your target packages, keeping it clean. - Works whether you're using the standard
package.json
dependencies approach or thepackage.json
array approach.
Cons:
- Like any target packages listed in a
package.json
array, each of thesupplement.json
packages are built from scratch. That means that you need to include the recursive build-time dependencies for your target packages insupplement.json
. That means that you must list the build-time dependencies of your target packages, the build-time dependencies of your build-time dependencies, the build-time dependnecies of the build-time dependencies of your build-time dependencies... - You have to keep track of another file.