Home Explore Blog Models CI



nixpkgs

8th chunk of `doc/languages-frameworks/javascript.section.md`
247a86335d3cdbedad452462216aba8c1d476d1970bff42a0000000100000fcb
NOTE: It is highly recommended to use a pinned version of pnpm (i.e., `pnpm_8` or `pnpm_9`), to increase future reproducibility. It might also be required to use an older version if the package needs support for a certain lock file version.

In case you are patching `package.json` or `pnpm-lock.yaml`, make sure to pass `finalAttrs.patches` to the function as well (i.e., `inherit (finalAttrs) patches`.

`pnpm.configHook` supports adding additional `pnpm install` flags via `pnpmInstallFlags` which can be set to a Nix string array:

```nix
{ pnpm }:

stdenv.mkDerivation (finalAttrs: {
  pname = "foo";
  version = "0-unstable-1980-01-01";

  src = {
    # ...
  };

  pnpmInstallFlags = [ "--shamefully-hoist" ];

  pnpmDeps = pnpm.fetchDeps { inherit (finalAttrs) pnpmInstallFlags; };
})
```

#### Dealing with `sourceRoot` {#javascript-pnpm-sourceRoot}

If the pnpm project is in a subdirectory, you can just define `sourceRoot` or `setSourceRoot` for `fetchDeps`.
If `sourceRoot` is different between the parent derivation and `fetchDeps`, you will have to set `pnpmRoot` to effectively be the same location as it is in `fetchDeps`.

Assuming the following directory structure, we can define `sourceRoot` and `pnpmRoot` as follows:

```
.
├── frontend
│   ├── ...
│   ├── package.json
│   └── pnpm-lock.yaml
└── ...
```

```nix
{
  # ...
  pnpmDeps = pnpm.fetchDeps {
    # ...
    sourceRoot = "${finalAttrs.src.name}/frontend";
  };

  # by default the working directory is the extracted source
  pnpmRoot = "frontend";
}
```

#### PNPM Workspaces {#javascript-pnpm-workspaces}

If you need to use a PNPM workspace for your project, then set `pnpmWorkspaces = [ "<workspace project name 1>" "<workspace project name 2>" ]`, etc, in your `pnpm.fetchDeps` call,
which will make PNPM only install dependencies for those workspace packages.

For example:

```nix
{
  # ...
  pnpmWorkspaces = [ "@astrojs/language-server" ];
  pnpmDeps = pnpm.fetchDeps {
    inherit (finalAttrs) pnpmWorkspaces;
    #...
  };
}
```

The above would make `pnpm.fetchDeps` call only install dependencies for the `@astrojs/language-server` workspace package.
Note that you do not need to set `sourceRoot` to make this work.

Usually, in such cases, you'd want to use `pnpm --filter=<pnpm workspace name> build` to build your project, as `npmHooks.npmBuildHook` probably won't work. A `buildPhase` based on the following example will probably fit most workspace projects:

```nix
{
  buildPhase = ''
    runHook preBuild

    pnpm --filter=@astrojs/language-server build

    runHook postBuild
  '';
}
```

#### Additional PNPM Commands and settings {#javascript-pnpm-extraCommands}

If you require setting an additional PNPM configuration setting (such as `dedupe-peer-dependents` or similar),
set `prePnpmInstall` to the right commands to run. For example:

```nix
{
  prePnpmInstall = ''
    pnpm config set dedupe-peer-dependants false
  '';
  pnpmDeps = pnpm.fetchDeps {
    inherit (finalAttrs) prePnpmInstall;
    # ...
  };
}
```

In this example, `prePnpmInstall` will be run by both `pnpm.configHook` and by the `pnpm.fetchDeps` builder.

#### PNPM `fetcherVersion` {#javascript-pnpm-fetcherVersion}

This is the version of the output of `pnpm.fetchDeps`, if you haven't set it already, you can use `1` with your current hash:

```nix
{
  # ...
  pnpmDeps = pnpm.fetchDeps {
    # ...
    fetcherVersion = 1;
    hash = "..."; # you can use your already set hash here
  };
}
```

After upgrading to a newer `fetcherVersion`, you need to regenerate the hash:

```nix
{
  # ...
  pnpmDeps = pnpm.fetchDeps {
    # ...
    fetcherVersion = 2;
    hash = "..."; # clear this hash and generate a new one
  };
}
```

This variable ensures that we can make changes to the output of `pnpm.fetchDeps` without breaking existing hashes.
Changes can include workarounds or bug fixes to existing PNPM issues.

##### Version history {#javascript-pnpm-fetcherVersion-versionHistory}

- 1: Initial version, nothing special

Title: Nixpkgs PNPM: Version Pinning, Advanced Configuration, Workspaces, and `fetcherVersion`
Summary
This document details advanced `pnpm` integration within Nixpkgs. It strongly recommends using pinned `pnpm` versions (e.g., `pnpm_8`) for reproducibility and lock file version compatibility. Instructions are provided for passing `finalAttrs.patches` when modifying `package.json` or `pnpm-lock.yaml`, and for using `pnpmInstallFlags` to add custom `pnpm install` arguments. The text also explains how to handle `pnpm` projects in subdirectories using `sourceRoot` for `fetchDeps` and `pnpmRoot` for the derivation. For PNPM Workspaces, it describes setting `pnpmWorkspaces` in `pnpm.fetchDeps` to install only specific workspace dependencies, and suggests a custom `buildPhase` for such projects. Additionally, it shows how to execute extra `pnpm` commands or configuration settings via `prePnpmInstall`. Finally, `fetcherVersion` is introduced as a mechanism to manage changes in the output of `pnpm.fetchDeps`, requiring hash regeneration upon version upgrades.