Skip to content

Commit

Permalink
yarnInstallHook: init (#328544)
Browse files Browse the repository at this point in the history
  • Loading branch information
philiptaron authored Sep 4, 2024
2 parents 9ac63f8 + feb1b53 commit afb866e
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 13,286 deletions.
13 changes: 9 additions & 4 deletions doc/languages-frameworks/javascript.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,7 @@ Yarn based projects use a `yarn.lock` file instead of a `package-lock.json` to p

- `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:

Expand Down Expand Up @@ -501,9 +502,9 @@ stdenv.mkDerivation (finalAttrs: {
nativeBuildInputs = [
yarnConfigHook
yarnBuildHook
yarnInstallHook
# Needed for executing package.json scripts
nodejs
npmHooks.npmInstallHook
];
meta = {
Expand All @@ -512,8 +513,6 @@ stdenv.mkDerivation (finalAttrs: {
})
```

Note that there is no setup hook for installing yarn based packages - `npmHooks.npmInstallHook` should fit most cases, but sometimes you may need to override the `installPhase` completely.

#### `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`.
Expand All @@ -525,9 +524,15 @@ This script by default runs `yarn --offline build`, and it relies upon the proje
- `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` and `yarnBuildHook`. 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).
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}

Expand Down
17 changes: 17 additions & 0 deletions pkgs/build-support/node/fetch-yarn-deps/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@
stdenv,
lib,
makeWrapper,
installShellFiles,
nodejsInstallManuals,
nodejsInstallExecutables,
coreutils,
nix-prefetch-git,
fetchurl,
jq,
nodejs,
nodejs-slim,
prefetch-yarn-deps,
fixup-yarn-lock,
Expand Down Expand Up @@ -175,4 +180,16 @@ in
description = "Run yarn build in buildPhase";
};
} ./yarn-build-hook.sh;

yarnInstallHook = makeSetupHook {
name = "yarn-install-hook";
propagatedBuildInputs = [
yarn
nodejsInstallManuals
nodejsInstallExecutables
];
substitutions = {
jq = lib.getExe jq;
};
} ./yarn-install-hook.sh;
}
79 changes: 79 additions & 0 deletions pkgs/build-support/node/fetch-yarn-deps/yarn-install-hook.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# shellcheck shell=bash

yarnInstallHook() {
echo "Executing yarnInstallHook"

runHook preInstall

local -r packageOut="$out/lib/node_modules/$(@jq@ --raw-output '.name' ./package.json)"
mkdir -p "$packageOut"

local -ar yarnArgs=(
--ignore-engines
--ignore-platform
--ignore-scripts
--no-progress
--non-interactive
--offline
)

local -r tmpDir="$(mktemp -d yarnInstallHook.XXXXXX)"

# yarn pack does not work at all with bundleDependencies.
# Since we are imediately unpacking, we can just remove them from package.json
# This will NOT be fixed in yarn v1: /~https://github.com/yarnpkg/yarn/issues/6794
mv ./package.json "$tmpDir/package.json.orig"
# Note: two spellings are accepted, 'bundleDependencies' and 'bundledDependencies'
@jq@ 'del(.bundleDependencies)|del(.bundledDependencies)' "$tmpDir/package.json.orig" > ./package.json

# TODO: figure out a way to avoid redundant compress/decompress steps
yarn pack \
--filename "$tmpDir/yarn-pack.tgz" \
"${yarnArgs[@]}"

tar xzf "$tmpDir/yarn-pack.tgz" \
-C "$packageOut" \
--strip-components 1 \
package/

mv "$tmpDir/package.json.orig" ./package.json

nodejsInstallExecutables ./package.json

nodejsInstallManuals ./package.json

local -r nodeModulesPath="$packageOut/node_modules"

if [ ! -d "$nodeModulesPath" ]; then
if [ -z "${yarnKeepDevDeps-}" ]; then
# Yarn has a 'prune' command, but it's only a stub that directs you to use install
if ! yarn install \
--frozen-lockfile \
--force \
--production=true \
"${yarnArgs[@]}"
then
echo
echo
echo "ERROR: yarn prune step failed"
echo
echo 'If yarn tried to download additional dependencies above, try setting `yarnKeepDevDeps = true`.'
echo

exit 1
fi
fi

find node_modules -maxdepth 1 -type d -empty -delete

cp -r node_modules "$nodeModulesPath"
fi

runHook postInstall

echo "Finished yarnInstallHook"
}

if [ -z "${dontYarnInstall-}" ] && [ -z "${installPhase-}" ]; then
installPhase=yarnInstallHook
fi
Loading

0 comments on commit afb866e

Please sign in to comment.