about summary refs log tree commit diff
path: root/doc/languages-frameworks/javascript.section.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/languages-frameworks/javascript.section.md')
-rw-r--r--doc/languages-frameworks/javascript.section.md220
1 files changed, 211 insertions, 9 deletions
diff --git a/doc/languages-frameworks/javascript.section.md b/doc/languages-frameworks/javascript.section.md
index 76db9d0007ce5..e68a29b0b3fdf 100644
--- a/doc/languages-frameworks/javascript.section.md
+++ b/doc/languages-frameworks/javascript.section.md
@@ -206,7 +206,7 @@ buildNpmPackage rec {
   NODE_OPTIONS = "--openssl-legacy-provider";
 
   meta = {
-    description = "A modern web UI for various torrent clients with a Node.js backend and React frontend";
+    description = "Modern web UI for various torrent clients with a Node.js backend and React frontend";
     homepage = "https://flood.js.org";
     license = lib.licenses.gpl3Only;
     maintainers = with lib.maintainers; [ winter ];
@@ -233,7 +233,7 @@ If these are not defined, `npm pack` may miss some files, and no binaries will b
 * `npmPruneFlags`: Flags to pass to `npm prune`. Defaults to the value of `npmInstallFlags`.
 * `makeWrapperArgs`: Flags to pass to `makeWrapper`, added to executable calling the generated `.js` with `node` as an interpreter. These scripts are defined in `package.json`.
 * `nodejs`: The `nodejs` package to build against, using the corresponding `npm` shipped with that version of `node`. Defaults to `pkgs.nodejs`.
-* `npmDeps`: The dependencies used to build the npm package. Especially useful to not have to recompute workspace depedencies.
+* `npmDeps`: The dependencies used to build the npm package. Especially useful to not have to recompute workspace dependencies.
 
 #### prefetch-npm-deps {#javascript-buildNpmPackage-prefetch-npm-deps}
 
@@ -258,19 +258,58 @@ It returns a derivation with all `package-lock.json` dependencies downloaded int
 
 #### importNpmLock {#javascript-buildNpmPackage-importNpmLock}
 
-`importNpmLock` is a Nix function that requires the following optional arguments:
+This function replaces the npm dependency references in `package.json` and `package-lock.json` with paths to the Nix store.
+How each dependency is fetched can be customized with the `fetcherOpts` argument.
 
-- `npmRoot`: Path to package directory containing the source tree
+This is a simpler and more convenient alternative to [`fetchNpmDeps`](#javascript-buildNpmPackage-fetchNpmDeps) for managing npm dependencies in Nixpkgs.
+There is no need to specify a `hash`, since it relies entirely on the integrity hashes already present in the `package-lock.json` file.
+
+##### Inputs {#javascript-buildNpmPackage-inputs}
+
+- `npmRoot`: Path to package directory containing the source tree.
+  If this is omitted, the `package` and `packageLock` arguments must be specified instead.
 - `package`: Parsed contents of `package.json`
 - `packageLock`: Parsed contents of `package-lock.json`
 - `pname`: Package name
 - `version`: Package version
+- `fetcherOpts`: An attribute set of arguments forwarded to the underlying fetcher.
 
 It returns a derivation with a patched `package.json` & `package-lock.json` with all dependencies resolved to Nix store paths.
 
-This function is analogous to using `fetchNpmDeps`, but instead of specifying `hash` it uses metadata from `package.json` & `package-lock.json`.
+:::{.note}
+`npmHooks.npmConfigHook` cannot be used with `importNpmLock`.
+Use `importNpmLock.npmConfigHook` instead.
+:::
+
+:::{.example}
+
+##### `pkgs.importNpmLock` usage example {#javascript-buildNpmPackage-example}
+```nix
+{ buildNpmPackage, importNpmLock }:
+
+buildNpmPackage {
+  pname = "hello";
+  version = "0.1.0";
+  src = ./.;
+
+  npmDeps = importNpmLock {
+    npmRoot = ./.;
+  };
+
+  npmConfigHook = importNpmLock.npmConfigHook;
+}
+```
+:::
+
+:::{.example}
+##### `pkgs.importNpmLock` usage example with `fetcherOpts` {#javascript-buildNpmPackage-example-fetcherOpts}
+
+`importNpmLock` uses the following fetchers:
 
-Note that `npmHooks.npmConfigHook` cannot be used with `importNpmLock`. You will instead need to use `importNpmLock.npmConfigHook`:
+- `pkgs.fetchurl` for `http(s)` dependencies
+- `builtins.fetchGit` for `git` dependencies
+
+It is possible to provide additional arguments to individual fetchers as needed:
 
 ```nix
 { buildNpmPackage, importNpmLock }:
@@ -278,14 +317,57 @@ Note that `npmHooks.npmConfigHook` cannot be used with `importNpmLock`. You will
 buildNpmPackage {
   pname = "hello";
   version = "0.1.0";
+  src = ./.;
 
   npmDeps = importNpmLock {
     npmRoot = ./.;
+    fetcherOpts = {
+      # Pass 'curlOptsList' to 'pkgs.fetchurl' while fetching 'axios'
+      { "node_modules/axios" = { curlOptsList = [ "--verbose" ]; }; }
+    };
   };
 
   npmConfigHook = importNpmLock.npmConfigHook;
 }
 ```
+:::
+
+#### importNpmLock.buildNodeModules {#javascript-buildNpmPackage-importNpmLock.buildNodeModules}
+
+`importNpmLock.buildNodeModules` returns a derivation with a pre-built `node_modules` directory, as imported by `importNpmLock`.
+
+This is to be used together with `importNpmLock.hooks.linkNodeModulesHook` to facilitate `nix-shell`/`nix develop` based development workflows.
+
+It accepts an argument with the following attributes:
+
+`npmRoot` (Path; optional)
+: Path to package directory containing the source tree. If not specified, the `package` and `packageLock` arguments must both be specified.
+
+`package` (Attrset; optional)
+: Parsed contents of `package.json`, as returned by `lib.importJSON ./my-package.json`. If not specified, the `package.json` in `npmRoot` is used.
+
+`packageLock` (Attrset; optional)
+: Parsed contents of `package-lock.json`, as returned `lib.importJSON ./my-package-lock.json`. If not specified, the `package-lock.json` in `npmRoot` is used.
+
+`derivationArgs` (`mkDerivation` attrset; optional)
+: Arguments passed to `stdenv.mkDerivation`
+
+For example:
+
+```nix
+pkgs.mkShell {
+  packages = [
+    importNpmLock.hooks.linkNodeModulesHook
+    nodejs
+  ];
+
+  npmDeps = importNpmLock.buildNodeModules {
+    npmRoot = ./.;
+    inherit nodejs;
+  };
+}
+```
+will create a development shell where a `node_modules` directory is created & packages symlinked to the Nix store when activated.
 
 ### corepack {#javascript-corepack}
 
@@ -346,11 +428,11 @@ NOTE: It is highly recommended to use a pinned version of pnpm (i.e. `pnpm_8` or
 
 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`.
 
-#### Dealing with `sourceRoot` {#javascript-pnpm-sourceRoot}
+`pnpm.configHook` supports adding additional `pnpm install` flags via `pnpmInstallFlags` which can be set to a Nix string array.
 
-NOTE: Nixpkgs pnpm tooling doesn't support building projects with a `pnpm-workspace.yaml`, or building monorepos. It maybe possible to use `pnpm.fetchDeps` for these projects, but it may be hard or impossible to produce a binary from such projects ([an example attempt](https://github.com/NixOS/nixpkgs/pull/290715#issuecomment-2144543728)).
+#### Dealing with `sourceRoot` {#javascript-pnpm-sourceRoot}
 
-If the pnpm project is in a subdirectory, you can just define `sourceRoot` or `setSourceRoot` for `fetchDeps`. Note, that projects using `pnpm-workspace.yaml` are currently not supported, and will probably not work using this approach.
+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:
@@ -375,8 +457,128 @@ Assuming the following directory structure, we can define `sourceRoot` and `pnpm
   pnpmRoot = "frontend";
 ```
 
+#### PNPM Workspaces {#javascript-pnpm-workspaces}
+
+If you need to use a PNPM workspace for your project, then set `pnpmWorkspace = "<workspace project name>"` in your `pnpm.fetchDeps` call,
+which will make PNPM only install dependencies for that workspace package.
+
+For example:
+
+```nix
+...
+pnpmWorkspace = "@astrojs/language-server";
+pnpmDeps = pnpm.fetchDeps {
+  inherit (finalAttrs) pnpmWorkspace;
+  ...
+}
+```
+
+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=$pnpmWorkspace 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.
+
+
+### Yarn {#javascript-yarn}
+
+Yarn based projects use a `yarn.lock` file instead of a `package-lock.json` to pin dependencies. Nixpkgs provides the Nix function `fetchYarnDeps` which fetches an offline cache suitable for running `yarn install` before building the project. In addition, Nixpkgs provides the hooks:
+
+- `yarnConfigHook`: Fetches the dependencies from the offline cache and installs them into `node_modules`.
+- `yarnBuildHook`: Runs `yarn build` or a specified `yarn` command that builds the project.
+- `yarnInstallHook`: Runs `yarn install --production` to prune dependencies and installs the project into `$out`.
+
+An example usage of the above attributes is:
+
+```nix
+{
+  lib,
+  stdenv,
+  fetchFromGitHub,
+  fetchYarnDeps,
+  yarnConfigHook,
+  yarnBuildHook,
+  yarnInstallHook,
+  nodejs,
+}:
+
+stdenv.mkDerivation (finalAttrs: {
+  pname = "...";
+  version = "...";
+
+  src = fetchFromGitHub {
+    owner = "...";
+    repo = "...";
+    rev = "v${finalAttrs.version}";
+    hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
+  };
+
+  yarnOfflineCache = fetchYarnDeps {
+    yarnLock = finalAttrs.src + "/yarn.lock";
+    hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
+  };
+
+  nativeBuildInputs = [
+    yarnConfigHook
+    yarnBuildHook
+    yarnInstallHook
+    # Needed for executing package.json scripts
+    nodejs
+  ];
+
+  meta = {
+    # ...
+  };
+})
+```
+
+#### `yarnConfigHook` arguments {#javascript-yarnconfighook}
+
+By default, `yarnConfigHook` relies upon the attribute `${yarnOfflineCache}` (or `${offlineCache}` if the former is not set) to find the location of the offline cache produced by `fetchYarnDeps`. To disable this phase, you can set `dontYarnInstallDeps = true` or override the `configurePhase`.
+
+#### `yarnBuildHook` arguments {#javascript-yarnbuildhook}
+
+This script by default runs `yarn --offline build`, and it relies upon the project's dependencies installed at `node_modules`. Below is a list of additional `mkDerivation` arguments read by this hook:
+
+- `yarnBuildScript`: Sets a different `yarn --offline` subcommand (defaults to `build`).
+- `yarnBuildFlags`: Single string list of additional flags to pass the above command, or a Nix list of such additional flags.
+
+#### `yarnInstallHook` arguments {#javascript-yarninstallhook}
+
+To install the package `yarnInstallHook` uses both `npm` and `yarn` to cleanup project files and dependencies. To disable this phase, you can set `dontYarnInstall = true` or override the `installPhase`. Below is a list of additional `mkDerivation` arguments read by this hook:
+
+- `yarnKeepDevDeps`: Disables the removal of devDependencies from `node_modules` before installation.
+
 ### yarn2nix {#javascript-yarn2nix}
 
+WARNING: The `yarn2nix` functions have been deprecated in favor of the new `yarnConfigHook`, `yarnBuildHook` and `yarnInstallHook`. Documentation for them still appears here for the sake of the packages that still use them. See also a tracking issue [#324246](https://github.com/NixOS/nixpkgs/issues/324246).
+
 #### Preparation {#javascript-yarn2nix-preparation}
 
 You will need at least a `yarn.lock` file. If upstream does not have one you need to generate it and reference it in your package definition.