fix(aionui): Use production-only deps for runtime, hoist transitive deps
Some checks failed
CI / check (push) Has been cancelled
Some checks failed
CI / check (push) Has been cancelled
Replace full node_modules copy with production-only FOD (mirrors the upstream Dockerfile pattern), reducing package output from ~6.9 GB to ~1.3 GB. Hoist @sentry/node to top-level node_modules so Electron's require() resolution can find it. Bun nests transitive deps inside .bun/ but Electron resolves from the realpath, requiring the dependency to be accessible from the walked-up directory chain.
This commit is contained in:
@@ -24,25 +24,19 @@ let
|
||||
hash = "sha256-A7dKGEuo5n+M7D9fJR3TN95q1P7En/ulsTO+ev6SAUY=";
|
||||
};
|
||||
|
||||
# Fixed-output derivation: fetch all pure-JS dependencies via bun.
|
||||
# We skip install scripts because they use #!/usr/bin/env shebangs
|
||||
# that don't exist in the Nix sandbox. Native addons are built
|
||||
# separately in the main derivation.
|
||||
bunDeps = stdenv.mkDerivation {
|
||||
name = "aionui-bun-deps-${version}";
|
||||
# FOD 1: All dependencies (dev + prod) for the build phase.
|
||||
bunBuildDeps = stdenv.mkDerivation {
|
||||
name = "aionui-build-deps-${version}";
|
||||
inherit src;
|
||||
nativeBuildInputs = [
|
||||
bun
|
||||
cacert
|
||||
];
|
||||
|
||||
outputHashAlgo = "sha256";
|
||||
outputHashMode = "recursive";
|
||||
outputHash = "sha256-Fuj55vxDgpx5A4iwnU/5IZKPfaYMH3DeZ1yauuZHn8g=";
|
||||
|
||||
dontPatchShebangs = true;
|
||||
dontFixup = true;
|
||||
|
||||
SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
|
||||
|
||||
buildPhase = ''
|
||||
@@ -54,10 +48,36 @@ let
|
||||
mkdir -p $out
|
||||
cp -r node_modules $out/
|
||||
cp -r packages $out/
|
||||
# Workspace packages reference root configs with relative paths
|
||||
cp tsconfig.json $out/
|
||||
'';
|
||||
};
|
||||
|
||||
# FOD 2: Production-only dependencies for the runtime output.
|
||||
# Mirrors the Dockerfile's `bun install --production --ignore-scripts`.
|
||||
bunProdDeps = stdenv.mkDerivation {
|
||||
name = "aionui-prod-deps-${version}";
|
||||
inherit src;
|
||||
nativeBuildInputs = [
|
||||
bun
|
||||
cacert
|
||||
];
|
||||
outputHashAlgo = "sha256";
|
||||
outputHashMode = "recursive";
|
||||
outputHash = "sha256-eCQ9ObhttZ10CehRRvl4IaOKkdK9m1TQJuhLmhiMkBY=";
|
||||
dontPatchShebangs = true;
|
||||
dontFixup = true;
|
||||
SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
|
||||
|
||||
buildPhase = ''
|
||||
export HOME=$TMPDIR
|
||||
bun install --frozen-lockfile --production --ignore-scripts
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp -r node_modules $out/
|
||||
'';
|
||||
};
|
||||
in
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
@@ -84,11 +104,10 @@ stdenv.mkDerivation rec {
|
||||
|
||||
export HOME=$TMPDIR
|
||||
|
||||
# Use the pre-fetched node_modules from the FOD (symlink farm)
|
||||
ln -sf ${bunDeps}/node_modules .
|
||||
# Use the full dependency set for the build
|
||||
ln -sf ${bunBuildDeps}/node_modules .
|
||||
|
||||
# ── Build better-sqlite3 native addon ──────────────────────
|
||||
# The FOD output is read-only; build in a temp dir.
|
||||
echo "Building better-sqlite3 from source..."
|
||||
BT3_SRC=$TMPDIR/bts3-src
|
||||
BT3_OUT=$TMPDIR/bts3-out
|
||||
@@ -103,23 +122,6 @@ stdenv.mkDerivation rec {
|
||||
cp build/Release/better_sqlite3.node "$BT3_OUT/build/Release/" 2>/dev/null || true
|
||||
)
|
||||
|
||||
# ── Build sharp native addon ──────────────────────────────
|
||||
echo "Building sharp from source..."
|
||||
SHARP_SRC=$TMPDIR/sharp-src
|
||||
SHARP_OUT=$TMPDIR/sharp-out
|
||||
mkdir -p "$SHARP_SRC" "$SHARP_OUT"
|
||||
cp -rL node_modules/sharp/* "$SHARP_SRC/" 2>/dev/null || true
|
||||
if [ -f "$SHARP_SRC/package.json" ]; then
|
||||
chmod -R u+w "$SHARP_SRC"
|
||||
(
|
||||
cd "$SHARP_SRC"
|
||||
export npm_config_nodedir=${nodejs}
|
||||
node-gyp rebuild 2>/dev/null || echo " sharp: build skipped (needs libvips)"
|
||||
mkdir -p "$SHARP_OUT/build/Release"
|
||||
cp build/Release/sharp.node "$SHARP_OUT/build/Release/" 2>/dev/null || true
|
||||
)
|
||||
fi
|
||||
|
||||
# ── electron-vite build ───────────────────────────────────
|
||||
echo "Running electron-vite build..."
|
||||
${nodejs}/bin/node node_modules/.bin/electron-vite build \
|
||||
@@ -142,34 +144,36 @@ stdenv.mkDerivation rec {
|
||||
cp -r public $out/lib/aionui/
|
||||
cp package.json $out/lib/aionui/
|
||||
|
||||
# ── Runtime dependencies ──────────────────────────────────
|
||||
# Copy node_modules (from the symlink) – the compiled output
|
||||
# has externalized require() calls for every dependency.
|
||||
cp -rL node_modules $out/lib/aionui/
|
||||
# ── Production-only node_modules (mirrors Dockerfile) ─────
|
||||
cp -a ${bunProdDeps}/node_modules $out/lib/aionui/node_modules
|
||||
chmod -R u+w $out/lib/aionui/node_modules
|
||||
|
||||
# Remove prebuilt musl (Alpine) binaries from sharp — they
|
||||
# are incompatible with glibc and we built from source anyway.
|
||||
find $out/lib/aionui/node_modules -path "*/sharp-linuxmusl*" -type d -exec rm -rf {} + 2>/dev/null || true
|
||||
find $out/lib/aionui/node_modules -path "*/sharp-libvips-linuxmusl*" -type d -exec rm -rf {} + 2>/dev/null || true
|
||||
# Remove workspace symlink – @aionui/web-host is bundled by
|
||||
# electron-vite (excluded from externalizeDepsPlugin), so the
|
||||
# symlink to packages/web-host is not needed at runtime.
|
||||
rm -f $out/lib/aionui/node_modules/@aionui/web-host
|
||||
|
||||
# ── Inject compiled native addons ─────────────────────────
|
||||
# cp -rL from the FOD preserves read-only permissions.
|
||||
# Make native addon dirs writable before overlaying binaries.
|
||||
chmod -R u+w $out/lib/aionui/node_modules/better-sqlite3 2>/dev/null || true
|
||||
chmod -R u+w $out/lib/aionui/node_modules/sharp 2>/dev/null || true
|
||||
|
||||
BT3_OUT=$TMPDIR/bts3-out
|
||||
if [ -f "$BT3_OUT/build/Release/better_sqlite3.node" ]; then
|
||||
mkdir -p $out/lib/aionui/node_modules/better-sqlite3/build/Release
|
||||
cp "$BT3_OUT/build/Release/better_sqlite3.node" \
|
||||
$out/lib/aionui/node_modules/better-sqlite3/build/Release/
|
||||
# @sentry/electron requires @sentry/node at runtime, but bun
|
||||
# nests it inside .bun/ rather than hoisting to top-level.
|
||||
# Electron's require() walks up from the resolved realpath
|
||||
# and needs it accessible either at top-level or via the
|
||||
# symlink target's node_modules. We ensure top-level access.
|
||||
if [ ! -e $out/lib/aionui/node_modules/@sentry/node ]; then
|
||||
SRC=$(echo $out/lib/aionui/node_modules/.bun/@sentry+node@*/node_modules/@sentry/node)
|
||||
if [ -d "$SRC" ]; then
|
||||
ln -sf "$(realpath --relative-to=$out/lib/aionui/node_modules/@sentry "$SRC")" \
|
||||
$out/lib/aionui/node_modules/@sentry/node
|
||||
fi
|
||||
fi
|
||||
|
||||
SHARP_OUT=$TMPDIR/sharp-out
|
||||
if [ -f "$SHARP_OUT/build/Release/sharp.node" ]; then
|
||||
mkdir -p $out/lib/aionui/node_modules/sharp/build/Release
|
||||
cp "$SHARP_OUT/build/Release/sharp.node" \
|
||||
$out/lib/aionui/node_modules/sharp/build/Release/
|
||||
# Inject compiled better-sqlite3 .node into the runtime tree
|
||||
if [ -f "$TMPDIR/bts3-out/build/Release/better_sqlite3.node" ]; then
|
||||
rm -rf $out/lib/aionui/node_modules/better-sqlite3
|
||||
cp -rL ${bunProdDeps}/node_modules/better-sqlite3 $out/lib/aionui/node_modules/better-sqlite3 2>/dev/null || true
|
||||
chmod -R u+w $out/lib/aionui/node_modules/better-sqlite3
|
||||
mkdir -p $out/lib/aionui/node_modules/better-sqlite3/build/Release
|
||||
cp "$TMPDIR/bts3-out/build/Release/better_sqlite3.node" \
|
||||
$out/lib/aionui/node_modules/better-sqlite3/build/Release/
|
||||
fi
|
||||
|
||||
# ── Desktop entry ─────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user