Skip to content

fix(plugin-vite): externalize native node modules#4232

Draft
erickzhao wants to merge 8 commits into
nextfrom
fix/vite-external-modules
Draft

fix(plugin-vite): externalize native node modules#4232
erickzhao wants to merge 8 commits into
nextfrom
fix/vite-external-modules

Conversation

@erickzhao

Copy link
Copy Markdown
Member
  • I have read the contribution documentation for this project.
  • I agree to follow the code of conduct that this project follows, as appropriate.
  • The changes are appropriately documented (if applicable).
  • The changes have sufficient test coverage (if applicable).
  • The testsuite passes successfully on my local machine (if applicable).

Summarize your changes:

@github-actions github-actions Bot added the next label Apr 21, 2026
claude added 5 commits July 6, 2026 20:38
…ked node_modules

Extend native module detection to cover the napi-rs / prebuilt-binary
convention: a package is treated as native when its package.json has a
napi field, or when one of its optionalDependencies resolves to an
installed platform package (a .node main, a root-level .node binary, or
os/cpu constraints with a nested .node binary — e.g. sharp,
@parcel/watcher, @libsql/client).

Replace the top-level-only dependency resolution in
walkTransitiveDependencies with Node-style resolution (nearest
node_modules first, then ancestor directories), so npm conflict-nesting
and workspace-hoisted layouts resolve correctly. Optional dependencies
are now walked too, silently skipping platform packages that are not
installed. Symlinked package directories (pnpm's default layout,
npm link) are followed via realpath, with a warning about the remaining
pnpm limitations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KhNR823EZtFRRnQVJBMo1t
…ing the copy allowlist

Previously the plugin backed off entirely when the user supplied their
own packagerConfig.ignore, which silently broke the native module copy
step: the externalized modules were never allowlisted, so the packaged
app was missing them at runtime.

The plugin now composes the two: a path is ignored if either the user's
ignore (function, RegExp, or array) or the plugin's logic excludes it,
but the paths the plugin needs to keep — /.vite, /package.json, the
/node_modules root and the externalized native module directories —
always survive, because without them the packaged app cannot start.

Also keep bare scope directories (e.g. /node_modules/@serialport) when
an allowlisted module lives under them; ignoring the scope directory
itself would prevent packager from ever descending into it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KhNR823EZtFRRnQVJBMo1t
Add a nativeModules option to the plugin config as a manual escape
hatch for the automatic native module detection:

- include forces packages into the externalize-and-copy set (rollup
  external list, packager copy allowlist, and their transitive
  dependencies).
- exclude removes detected packages so Vite bundles them normally.

The overrides are applied both in the main/preload Vite config
generation (which runs in subprocess workers, so nativeModules is now
part of the serialized worker config) and in the prePackage detection
that feeds the packager ignore allowlist. Documented in the README.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KhNR823EZtFRRnQVJBMo1t
The vite-typescript template's declarations.d.ts references
@electron-forge/plugin-vite/forge-vite-env, which imports src/Config.ts
from the published package sources. Importing NativeModulesConfig from
detect-native-modules.ts pulled that implementation file (and its
untyped 'debug' import) into the scaffolded app's tsc graph, failing
'npm run typecheck' with TS7016 since consumers don't have @types/debug.

Move the NativeModulesConfig interface into Config.ts alongside the
other plugin config interfaces and invert the import, so the consumer
graph stays limited to the type-only config surface as before.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KhNR823EZtFRRnQVJBMo1t
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants