Skip to content

Commit 52fbd58

Browse files
committed
Fix pnpm scope package issue
1 parent 66fec13 commit 52fbd58

2 files changed

Lines changed: 44 additions & 8 deletions

File tree

.agents/skills/smbcloud-deploy-nextjs/SKILL.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,13 @@ Fix:
310310
311311
### `Cannot find module 'styled-jsx'`, `@swc/helpers`, or other pnpm peer deps
312312
313+
A common concrete failure looks like:
314+
315+
- `code: 'MODULE_NOT_FOUND'`
316+
- `path: '/home/git/apps/web/<app>/node_modules/@swc/helpers'`
317+
318+
That usually means the standalone upload succeeded, but the top-level hoisted symlink for a scoped package was not recreated on the server.
319+
313320
Cause:
314321
315322
- pnpm stores peer dependencies inside `node_modules/.pnpm/<pkg>@<version>/node_modules/<pkg>` with internal symlinks that Node's standard `require.resolve()` cannot follow
@@ -318,10 +325,15 @@ Cause:
318325
319326
Fix:
320327
321-
- the CLI deploy script now auto-hoists: after uploading standalone output, it scans `node_modules/.pnpm/*/node_modules/*` and creates symlinks at `node_modules/<pkg>` for any packages not already present
322-
- this restores the resolution structure that pnpm normally provides via its `.pnpm/node_modules/` virtual directory
323-
- no manual intervention needed for new deploys
324-
- to fix a server manually: `find node_modules/.pnpm -mindepth 2 -maxdepth 2 -type d -name node_modules` and symlink each child into the root `node_modules/`
328+
- the CLI deploy script now auto-hoists in two passes:
329+
- first mirror pnpm's virtual directory at `node_modules/.pnpm/node_modules/*`
330+
- then fall back to scanning `node_modules/.pnpm/*/node_modules/*` for anything still missing
331+
- this preserves pnpm's exact resolved package choice and fixes scoped packages like `@swc/helpers` as well as unscoped ones like `styled-jsx`
332+
- no manual intervention needed for new deploys once the updated CLI is used
333+
- to fix a server manually, prefer pnpm's virtual directory as the source of truth:
334+
- create `node_modules/@scope/` directories as needed
335+
- symlink `node_modules/<pkg>` or `node_modules/@scope/<pkg>` to the corresponding entry under `node_modules/.pnpm/node_modules/`
336+
- only if that directory is missing, scan individual `.pnpm/<store-entry>/node_modules/*` folders as a fallback
325337
326338
### Wrong port after deploy
327339

crates/cli/src/deploy/process_deploy_nextjs_ssr.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -456,9 +456,30 @@ ECOSYSTEM_EOF
456456
457457
# pnpm standalone output buries peer deps inside node_modules/.pnpm/
458458
# without the top-level symlinks Node needs for require.resolve().
459-
# Scan the .pnpm store and create flat symlinks. For scoped packages,
460-
# always force-replace partial rsync copies with symlinks to the .pnpm
461-
# store entry that has the most content (not just package.json).
459+
# First mirror pnpm's own virtual node_modules directory when it exists —
460+
# this preserves the exact version selection pnpm already resolved, which is
461+
# especially important for scoped packages like @swc/helpers.
462+
# Then fall back to scanning individual .pnpm store entries for anything the
463+
# virtual directory did not expose.
464+
if [ -d "node_modules/.pnpm/node_modules" ]; then
465+
for pkg_path in node_modules/.pnpm/node_modules/*; do
466+
[ -e "$pkg_path" ] || continue
467+
pkg_name=$(basename "$pkg_path")
468+
if [ "${{pkg_name:0:1}}" = "@" ] && [ -d "$pkg_path" ]; then
469+
mkdir -p "node_modules/$pkg_name"
470+
for sub_path in "$pkg_path"/*; do
471+
[ -e "$sub_path" ] || continue
472+
sub_name=$(basename "$sub_path")
473+
rm -rf "node_modules/$pkg_name/$sub_name"
474+
ln -sfn "$APP_PATH/$sub_path" "node_modules/$pkg_name/$sub_name"
475+
done
476+
else
477+
rm -rf "node_modules/$pkg_name"
478+
ln -sfn "$APP_PATH/$pkg_path" "node_modules/$pkg_name"
479+
fi
480+
done
481+
fi
482+
462483
if [ -d "node_modules/.pnpm" ]; then
463484
find node_modules/.pnpm -mindepth 2 -maxdepth 2 -type d -name "node_modules" 2>/dev/null | while read pnpm_nm; do
464485
for pkg_path in "$pnpm_nm"/*; do
@@ -484,7 +505,10 @@ ECOSYSTEM_EOF
484505
fi
485506
done
486507
else
487-
[ -e "node_modules/$pkg_name" ] || ln -sfn "$APP_PATH/$pkg_path" "node_modules/$pkg_name"
508+
if [ -e "node_modules/$pkg_name" ]; then
509+
continue
510+
fi
511+
ln -sfn "$APP_PATH/$pkg_path" "node_modules/$pkg_name"
488512
fi
489513
done
490514
done

0 commit comments

Comments
 (0)