- 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
node2nixtool can have NPM package versions affixed to the attribute, depending on hownode2nixis set up. Version^0.0.1-1ofredux-devtools-climay 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-shelland specifically the shell derivation generated bynode2nix. For example, you can't expose NPM packages to your system environment by putting them inside thedependenciesfield of a dummypackage.jsonand 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 usingoverrideAttrsand the like, which isn't a clean approach.node2nixdoesn'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.jsonand use the-ioption. 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
dependenciesfield of a standardpackage.json,node2nixbuilds every package installed this way from scratch usingnpm rebuildon 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
node2nixin 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 standardnode2nixwithout 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
node2nixthat has your target packages, keeping it clean. - Works whether you're using the standard
package.jsondependencies approach or thepackage.jsonarray approach.
Cons:
- Like any target packages listed in a
package.jsonarray, each of thesupplement.jsonpackages 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.