mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-10-02 13:00:23 +00:00
doc/javascript: various fixes (#567490)
This commit is contained in:
@@ -1,142 +0,0 @@
|
||||
# pnpmBuildHook {#pnpm-build-hook}
|
||||
|
||||
[pnpm](https://pnpm.io/) is a an NPM-compatible package manager focused on increasing managment speeds, and reducing disk space.
|
||||
|
||||
The `pnpmBuildHook` in Nixpkgs overrides the default build phase for building packages that use pnpm.
|
||||
|
||||
:::{.example #ex-pnpm-build-hook}
|
||||
## pnpmBuildHook example code snippet {#pnpm-build-hook-code-snippet}
|
||||
|
||||
```nix
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
fetchPnpmDeps,
|
||||
pnpmConfigHook,
|
||||
pnpmBuildHook,
|
||||
makeBinaryWrapper,
|
||||
pnpm_10,
|
||||
}:
|
||||
let
|
||||
pnpm = pnpm_10;
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "coolPackages";
|
||||
version = "1.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "JaneCool";
|
||||
repo = "coolpackage";
|
||||
tag = finalAttrs.version;
|
||||
hash = lib.fakeHash;
|
||||
};
|
||||
|
||||
__structuredAttrs = true;
|
||||
strictDeps = true;
|
||||
|
||||
pnpmDeps = fetchPnpmDeps {
|
||||
inherit (finalAttrs) pname version src;
|
||||
inherit pnpm;
|
||||
fetcherVersion = 4;
|
||||
hash = lib.fakeHash;
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
pnpmConfigHook
|
||||
pnpmBuildHook
|
||||
makeBinaryWrapper
|
||||
];
|
||||
|
||||
pnpmBuildScript = "build";
|
||||
pnpmBuildFlags = [
|
||||
"--mode"
|
||||
"production"
|
||||
];
|
||||
pnpmWorkspaces = [
|
||||
"test"
|
||||
];
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir "$out"
|
||||
cp -r dist/. "$out"
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "very cool package that does cool things";
|
||||
mainProgram = "cool";
|
||||
};
|
||||
})
|
||||
```
|
||||
:::
|
||||
|
||||
## Variables controlling pnpmBuildHook {#pnpm-build-hook-variables}
|
||||
|
||||
### pnpm Exclusive Variables {#pnpm-build-hook-exclusive-variables}
|
||||
|
||||
#### `pnpmBuildScript` {#pnpm-build-hook-script}
|
||||
|
||||
Controls the script ran to build the package, by default the script is `build`.
|
||||
|
||||
#### `pnpmFlags` {#pnpm-build-hook-flags}
|
||||
|
||||
Controls flags used for all invocations of pnpm across all hooks local to this derivation.
|
||||
|
||||
#### `pnpmBuildFlags` {#pnpm-build-hook-build-flags}
|
||||
|
||||
Controls the flags pass only to the pnpm build script invocation.
|
||||
|
||||
#### `dontPnpmBuild` {#pnpm-build-hook-dont}
|
||||
|
||||
Disables automatically running `pnpmBuildHook`. The build can still be run manually if needed, for example:
|
||||
|
||||
```nix
|
||||
{
|
||||
lib,
|
||||
rustPlatform,
|
||||
pnpmBuildHook,
|
||||
pnpmConfigHook,
|
||||
fetchPnpmDeps,
|
||||
emptyDirectory,
|
||||
pnpm_10,
|
||||
}:
|
||||
let
|
||||
pnpm = pnpm_10;
|
||||
in
|
||||
rustPlatform.buildRustPackage (finalAttrs: {
|
||||
pname = "super-fast-application";
|
||||
version = "1.0";
|
||||
|
||||
src = emptyDirectory;
|
||||
|
||||
cargoHash = lib.fakeHash;
|
||||
|
||||
nativeBuildInputs = [
|
||||
pnpmBuildHook
|
||||
pnpmConfigHook
|
||||
];
|
||||
|
||||
pnpmDeps = fetchPnpmDeps {
|
||||
inherit (finalAttrs) pname version src;
|
||||
inherit pnpm;
|
||||
fetcherVersion = 4;
|
||||
hash = lib.fakeHash;
|
||||
};
|
||||
|
||||
dontPnpmBuild = true;
|
||||
postBuild = ''
|
||||
pnpmBuildHook
|
||||
'';
|
||||
})
|
||||
```
|
||||
|
||||
### Honored Variables {#pnpm-build-hook-honored-variables}
|
||||
|
||||
The following variables are honored by `pnpmBuildHook`.
|
||||
|
||||
* [`pnpmRoot`](#javascript-pnpm-sourceRoot)
|
||||
* [`pnpmWorkspaces`](#javascript-pnpm-workspaces)
|
||||
@@ -6,6 +6,12 @@ Package JavaScript applications with the tools below.
|
||||
|
||||
## Tools overview {#javascript-tools-overview}
|
||||
|
||||
- **npm**: [`buildNpmPackage`](#javascript-buildNpmPackage), [`prefetch-npm-deps` (CLI)](#javascript-buildNpmPackage-prefetch-npm-deps), [`fetchNpmDeps`](#javascript-buildNpmPackage-fetchNpmDeps), [`importNpmLock`](#javascript-buildNpmPackage-importNpmLock)
|
||||
- [**corepack**](#javascript-corepack)
|
||||
- **pnpm**: [`fetchPnpmDeps`](#javascript-pnpm), [`pnpmConfigHook`](#javascript-pnpm-pnpmConfigHook), [`pnpmBuildHook`](#javascript-pnpm-pnpmBuildHook)
|
||||
- [**Yarn v1**](#javascript-yarn-v1): [`fetchYarnDeps`](#javascript-fetchyarndeps), [`yarnConfigHook`](#javascript-yarnconfighook), [`yarnBuildHook`](#javascript-yarnbuildhook), [`yarnInstallHook`](#javascript-yarninstallhook)
|
||||
- [**Yarn Berry (v3/v4)**](#javascript-yarn-v3-v4): [`fetchYarnBerryDeps`](#javascript-fetchYarnBerryDeps), [`yarnBerryConfigHook`](#javascript-yarnBerryConfigHook)
|
||||
|
||||
## General principles {#javascript-general-principles}
|
||||
|
||||
The principles below are ordered by importance.
|
||||
@@ -288,9 +294,7 @@ This package puts the corepack wrappers for pnpm and yarn in your PATH, and they
|
||||
|
||||
pnpm is available as the top-level package `pnpm`. Additionally, there are variants pinned to certain major versions, like `pnpm_9`, `pnpm_10`, `pnpm_10_29_2` and `pnpm_11`, which support different sets of lock file versions.
|
||||
|
||||
When packaging an application that includes a `pnpm-lock.yaml`, you need to fetch the pnpm store for that project using a fixed-output-derivation. The function `fetchPnpmDeps` can create this pnpm store derivation. In conjunction, the setup hook `pnpmConfigHook` prepares the build environment to install the pre-fetched dependencies store. The example below uses the fetcher and setup hook for a package that has `package.json` and `pnpm-lock.yaml`:
|
||||
|
||||
There is also the [`pnpmBuildHook`](#pnpm-build-hook) for building packages with `pnpm`, as seen in [](#ex-pnpm-build-hook).
|
||||
When packaging an application that includes a `pnpm-lock.yaml`, you need to fetch the pnpm store for that project using a fixed-output-derivation. The function `fetchPnpmDeps` can create this pnpm store derivation. In conjunction, the setup hook [`pnpmConfigHook`](#javascript-pnpm-pnpmConfigHook) prepares the build environment to install the pre-fetched dependencies store. The example below uses the fetcher and setup hook for a package that has `package.json` and `pnpm-lock.yaml`:
|
||||
|
||||
```nix
|
||||
{
|
||||
@@ -298,6 +302,7 @@ There is also the [`pnpmBuildHook`](#pnpm-build-hook) for building packages with
|
||||
nodejs,
|
||||
pnpm_11,
|
||||
pnpmConfigHook,
|
||||
pnpmBuildHook,
|
||||
stdenv,
|
||||
}:
|
||||
let
|
||||
@@ -319,7 +324,8 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
nativeBuildInputs = [
|
||||
nodejs # in case scripts are run outside of a pnpm call
|
||||
pnpmConfigHook
|
||||
pnpm # At least required by pnpmConfigHook, if not other (custom) phases
|
||||
pnpmBuildHook
|
||||
pnpm # At least required by pnpmConfigHook and pnpmBuildHook, if not other (custom) phases
|
||||
];
|
||||
|
||||
pnpmDeps = fetchPnpmDeps {
|
||||
@@ -331,49 +337,11 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
})
|
||||
```
|
||||
|
||||
Use a pinned version of pnpm (for example `pnpm_9` or `pnpm_10`) to increase reproducibility. An older version may be required if the package needs a certain lock file version. To do so, pass the `pnpm` argument to `fetchPnpmDeps`. Then override the `pnpm` arg in `pnpmConfigHook`. Here are the changes in the example above to use a pinned pnpm version:
|
||||
The example also uses [`pnpmBuildHook`](#javascript-pnpm-pnpmBuildHook), which runs `pnpm run build` in the build phase.
|
||||
|
||||
<!-- TODO: Does splicing still work when overriding in nativeBuildInputs here? -->
|
||||
In case you are patching `package.json` or `pnpm-lock.yaml`, make sure to pass `finalAttrs.patches` to the `fetchPnpmDeps` function as well (i.e., `inherit (finalAttrs) patches`).
|
||||
|
||||
```diff
|
||||
{
|
||||
fetchPnpmDeps,
|
||||
nodejs,
|
||||
- pnpm,
|
||||
+ pnpm_10,
|
||||
pnpmConfigHook,
|
||||
stdenv,
|
||||
}:
|
||||
+let
|
||||
+ # Optionally override pnpm to use a custom nodejs version
|
||||
+ # Make sure that the same nodejs version is referenced in nativeBuildInputs
|
||||
+ # pnpm = pnpm_10.override { nodejs-slim = nodejs-slim_22; };
|
||||
+in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "foo";
|
||||
version = "0-unstable-1980-01-01";
|
||||
|
||||
src = {
|
||||
#...
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
nodejs # in case scripts are run outside of a pnpm call
|
||||
pnpmConfigHook
|
||||
- pnpm # At least required by pnpmConfigHook, if not other (custom) phases
|
||||
+ pnpm_10 # At least required by pnpmConfigHook, if not other (custom) phases
|
||||
];
|
||||
|
||||
pnpmDeps = fetchPnpmDeps {
|
||||
inherit (finalAttrs) pname version src;
|
||||
+ pnpm = pnpm_10;
|
||||
fetcherVersion = 4;
|
||||
hash = "...";
|
||||
};
|
||||
})
|
||||
```
|
||||
|
||||
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`).
|
||||
#### pnpmConfigHook {#javascript-pnpm-pnpmConfigHook}
|
||||
|
||||
`pnpmConfigHook` supports adding additional `pnpm install` flags via `pnpmInstallFlags` which can be set to a Nix string array:
|
||||
|
||||
@@ -391,6 +359,33 @@ In case you are patching `package.json` or `pnpm-lock.yaml`, make sure to pass `
|
||||
|
||||
If needed, set `dontPnpmConfigure = true;` to fully disable `pnpmConfigHook` without removing it from inputs manually.
|
||||
|
||||
#### pnpmBuildHook {#javascript-pnpm-pnpmBuildHook}
|
||||
|
||||
The `pnpmBuildHook` in overrides the default build phase with `pnpm run <build-script>`.
|
||||
|
||||
```nix
|
||||
{
|
||||
nativeBuildInputs = [
|
||||
pnpmBuildHook
|
||||
];
|
||||
|
||||
pnpmBuildScript = "build-ui";
|
||||
pnpmBuildFlags = [
|
||||
"--mode"
|
||||
"production"
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
Available options:
|
||||
|
||||
- `pnpmBuildScript`: select which script from `package.json` to run. Defaults to `build`.
|
||||
- `pnpmBuildFlags`: array of flags to pass to the build script.
|
||||
- `pnpmFlags`: currently the same as `pnpmBuildFlags`, but might be used by other hooks in the future.
|
||||
- `dontPnpmBuild`: disable this hook from running automatically. The hook can still be invoked manually.
|
||||
|
||||
Both [`pnpmRoot`](#javascript-pnpm-sourceRoot) and [`pnpmWorkspaces`](#javascript-pnpm-workspaces) are honored by this hook.
|
||||
|
||||
#### Dealing with `sourceRoot` {#javascript-pnpm-sourceRoot}
|
||||
|
||||
If the pnpm project is in a subdirectory, you can define `sourceRoot` or `setSourceRoot` for `fetchPnpmDeps`.
|
||||
@@ -603,13 +598,8 @@ To install the package, `yarnInstallHook` uses both `npm` and `yarn` to clean up
|
||||
- `yarnKeepDevDeps`: Disables the removal of devDependencies from `node_modules` before installation.
|
||||
|
||||
#### Yarn Berry v3/v4 {#javascript-yarn-v3-v4}
|
||||
Yarn Berry (v3 / v4) versions have similar formats. They start with blocks like these:
|
||||
|
||||
```yaml
|
||||
__metadata:
|
||||
version: 6
|
||||
cacheKey: 8[cX]
|
||||
```
|
||||
Yarn Berry (v3 / v4) versions have similar formats. The `yarn.lock` file starts with blocks like these:
|
||||
|
||||
```yaml
|
||||
__metadata:
|
||||
@@ -634,7 +624,6 @@ Explicitly pin the major version. For example, capture the `yarn-berry_Xn` argum
|
||||
|
||||
let
|
||||
yarn-berry = yarn-berry_4;
|
||||
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "foo";
|
||||
@@ -657,6 +646,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
```
|
||||
|
||||
##### `yarn-berry_X.fetchYarnBerryDeps` {#javascript-fetchYarnBerryDeps}
|
||||
|
||||
`fetchYarnBerryDeps` runs `yarn-berry-fetcher fetch` in a fixed-output-derivation. It is a custom fetcher designed to reproducibly download all files in the `yarn.lock` file, validating their hashes in the process. For git dependencies, it creates a checkout at `${offlineCache}/checkouts/<40-character-commit-hash>` (relying on the git commit hash to describe the contents of the checkout).
|
||||
|
||||
To produce the `hash` argument for the `fetchYarnBerryDeps` call, run `yarn-berry-fetcher prefetch`:
|
||||
@@ -668,14 +658,17 @@ $ yarn-berry-fetcher prefetch </path/to/yarn.lock> [/path/to/missing-hashes.json
|
||||
This prints the hash to stdout. Use it in update scripts to recalculate the hash for a new `yarn.lock`.
|
||||
|
||||
##### `yarn-berry_X.yarnBerryConfigHook` {#javascript-yarnBerryConfigHook}
|
||||
|
||||
`yarnBerryConfigHook` uses the store path `offlineCache` points to, to run a `yarn install` during the build, producing a usable `node_modules` directory from the downloaded dependencies.
|
||||
|
||||
Internally, this uses a patched version of Yarn to ensure git dependencies are re-packed and any attempted downloads fail immediately.
|
||||
|
||||
##### Patching the project's `package.json` or `yarn.lock` files {#javascript-yarnBerry-patching}
|
||||
|
||||
In case patching the project's `package.json` or `yarn.lock` is needed, it's important to pass `finalAttrs.patches` to `fetchYarnBerryDeps` as well, so the patched variants are picked up (i.e., `inherit (finalAttrs) patches`).
|
||||
|
||||
##### Missing hashes in the `yarn.lock` file {#javascript-yarnBerry-missing-hashes}
|
||||
|
||||
Unfortunately, `yarn.lock` files do not include hashes for optional/platform-specific dependencies. This is [by design](https://github.com/yarnpkg/berry/issues/6759).
|
||||
|
||||
To compensate for this, run the `yarn-berry-fetcher missing-hashes` subcommand to produce all missing hashes. These are stored in a `missing-hashes.json` file, which needs to be passed to both the build itself, as well as the `fetchYarnBerryDeps` helper:
|
||||
@@ -689,7 +682,6 @@ To compensate for this, run the `yarn-berry-fetcher missing-hashes` subcommand t
|
||||
|
||||
let
|
||||
yarn-berry = yarn-berry_4;
|
||||
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "foo";
|
||||
|
||||
@@ -430,9 +430,6 @@
|
||||
{
|
||||
"file": "hooks/pkg-config.section.md"
|
||||
},
|
||||
{
|
||||
"file": "hooks/pnpm.section.md"
|
||||
},
|
||||
{
|
||||
"file": "hooks/postgresql-test-hook.section.md"
|
||||
},
|
||||
|
||||
@@ -128,9 +128,6 @@
|
||||
"ex-pkgs-replace-vars-with": [
|
||||
"index.html#ex-pkgs-replace-vars-with"
|
||||
],
|
||||
"ex-pnpm-build-hook": [
|
||||
"index.html#ex-pnpm-build-hook"
|
||||
],
|
||||
"ex-shfmt": [
|
||||
"index.html#ex-shfmt"
|
||||
],
|
||||
@@ -406,33 +403,6 @@
|
||||
"pkgs.treefmt.withConfig": [
|
||||
"index.html#pkgs.treefmt.withConfig"
|
||||
],
|
||||
"pnpm-build-hook": [
|
||||
"index.html#pnpm-build-hook"
|
||||
],
|
||||
"pnpm-build-hook-build-flags": [
|
||||
"index.html#pnpm-build-hook-build-flags"
|
||||
],
|
||||
"pnpm-build-hook-code-snippet": [
|
||||
"index.html#pnpm-build-hook-code-snippet"
|
||||
],
|
||||
"pnpm-build-hook-dont": [
|
||||
"index.html#pnpm-build-hook-dont"
|
||||
],
|
||||
"pnpm-build-hook-exclusive-variables": [
|
||||
"index.html#pnpm-build-hook-exclusive-variables"
|
||||
],
|
||||
"pnpm-build-hook-flags": [
|
||||
"index.html#pnpm-build-hook-flags"
|
||||
],
|
||||
"pnpm-build-hook-script": [
|
||||
"index.html#pnpm-build-hook-script"
|
||||
],
|
||||
"pnpm-build-hook-variables": [
|
||||
"index.html#pnpm-build-hook-variables"
|
||||
],
|
||||
"pnpm-build-hook-honored-variables": [
|
||||
"index.html#pnpm-build-hook-honored-variables"
|
||||
],
|
||||
"preface": [
|
||||
"index.html#preface",
|
||||
"index.html#overview-of-nixpkgs"
|
||||
@@ -3886,7 +3856,23 @@
|
||||
"index.html#javascript-corepack"
|
||||
],
|
||||
"javascript-pnpm": [
|
||||
"index.html#javascript-pnpm"
|
||||
"index.html#javascript-pnpm",
|
||||
"index.html#ex-pnpm-build-hook"
|
||||
],
|
||||
"javascript-pnpm-pnpmBuildHook": [
|
||||
"index.html#javascript-pnpm-pnpmBuildHook",
|
||||
"index.html#pnpm-build-hook",
|
||||
"index.html#pnpm-build-hook-build-flags",
|
||||
"index.html#pnpm-build-hook-code-snippet",
|
||||
"index.html#pnpm-build-hook-dont",
|
||||
"index.html#pnpm-build-hook-exclusive-variables",
|
||||
"index.html#pnpm-build-hook-flags",
|
||||
"index.html#pnpm-build-hook-script",
|
||||
"index.html#pnpm-build-hook-variables",
|
||||
"index.html#pnpm-build-hook-honored-variables"
|
||||
],
|
||||
"javascript-pnpm-pnpmConfigHook": [
|
||||
"index.html#javascript-pnpm-pnpmConfigHook"
|
||||
],
|
||||
"javascript-pnpm-sourceRoot": [
|
||||
"index.html#javascript-pnpm-sourceRoot"
|
||||
|
||||
Reference in New Issue
Block a user