GeezerVison is showing github.com — feat(webpack,vite): keep ns: builtin module imports for the runtime by edusperoni · Pull Request #11626 · NativeScript/NativeScript
Conversation
edusperoni
commented
Nov 9, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
PR Checklist
What is the current behavior?
The iOS and Android runtimes resolve ns:<name> builtin modules (ns:util, ns:module, ns:runtime, ns:url, ns:worker_threads, …) and a few node:<name> compatibility shims themselves, before any file or npm resolution. Neither bundler lets these imports through:
- webpack treats
ns:util as a URL scheme, which skips resolve.alias, and fails with UnhandledSchemeError. node:* fails the same way, because externalsPresets.node is off.
- Vite fails with
Rolldown failed to resolve import "ns:util", and silently replaces node:url / node:util / node:worker_threads with an empty browser stub. Under HMR, several dev-server passes also rewrite or stub these specifiers: /@id/ wrapping, routing to /ns/m/node_modules/ns:util, the esbuild dependency bundles, the dev import map, and the CommonJS require shim.
What is the new behavior?
Every ns: import is left verbatim in the output. Specifiers are matched by the ns: prefix, so modules added in future runtime versions work without changes here. ESM output keeps import … from "ns:util"; CommonJS output keeps require("ns:util").
Customization uses each bundler's own mechanisms:
webpack: the base config registers NativeScriptBuiltinModulesPlugin (default include: [/^ns:/]).
- Change its
include list with webpack-chain: config.plugin('NativeScriptBuiltinModulesPlugin').tap(...).
- The plugin matches on the request after
beforeResolve, so a stock NormalModuleReplacementPlugin can:
- redirect a builtin to a polyfill (
/^ns:url$/ → a file);
- forward a bare name to a runtime shim (
/^worker_threads$/ → node:worker_threads).
Vite: the base config adds nativescriptBuiltinModules().
- Add another instance with
{ include: ['node:worker_threads'] } to opt in more specifiers.
resolve.alias handles polyfills and forwarding, since aliases resolve before the plugin.
node: stays opt-in rather than hardcoding the current shim list, because the set grows with each runtime version. Both READMEs show how to forward to the runtime's shims, using worker_threads as the example.
Vite coverage:
vite build: the plugin runs first in the main build, worker builds and the dependency optimizer.
- HMR:
- an esbuild counterpart runs first in the deps, vendor and core bundles;
/@id/<builtin> is unwrapped before the device rewriting passes;
- guards in core
rewriteSpec, worker-realm module bindings and the plugin-specifier check keep these imports untouched;
- opted-in
node: names are left out of the dev import map;
- the CommonJS
require shim tries the runtime's require first for ns: / node: ids.
Tests:
packages/webpack5/__tests__/plugins/NativeScriptBuiltinModulesPlugin.spec.ts: real webpack compiles checking ESM and CommonJS output, polyfill and forwarding through NormalModuleReplacementPlugin, and the build failure without the plugin.
packages/vite/helpers/builtin-modules.spec.ts: in-process vite build (ESM, import(), require() in a CommonJS dependency, alias forwarding and polyfill, and the failure without the plugin), plus the esbuild plugin.
packages/vite/hmr/server/builtin-modules-hmr.spec.ts: each HMR touch point. All four tests fail without the HMR changes.
Notes for reviewers:
- The webpack config snapshots already fail on
main: they contain absolute paths from another machine and a FixSourceMapUrlPlugin that no longer exists. I added only the new plugin entry to them rather than regenerating. The set of failing tests is identical to main. The mdn-data alias re-wrap in base.ts comes from the prettier pre-commit hook.
packages/vite/typescript-optional.spec.ts also fails on main (5 tests) and is unchanged by this PR.
- Under HMR, the esbuild dependency bundles don't see Vite's
resolve.alias. A ns: polyfill or bare-name forward set up with an alias applies to vite build and the Vite module graph, but not to dependencies bundled by esbuild during a dev session.
- No on-device run yet. Manual check: import
ns:util from app code, a CommonJS dependency and a worker. Opt in node:worker_threads and check that it reaches the runtime, under both ns run (HMR) and a release build.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
The iOS and Android runtimes resolve `ns:<name>` builtin modules (and a
few `node:<name>` compatibility shims) themselves. Webpack failed on these
imports with an unhandled-scheme error, and Vite failed to resolve `ns:`
specifiers and replaced `node:` ones with an empty browser stub.
Every `ns:` specifier is now left verbatim in the output, matched by
prefix so modules added in future runtime versions work without changes.
Both packages expose the same helpers:
- addBuiltinModule(matcher, target?) opts more specifiers in, e.g. the
`node:` shims a runtime version ships, optionally forwarding a bare
specifier such as `worker_threads` to `node:worker_threads`.
- polyfillBuiltinModule(specifier, path) bundles a replacement instead,
for runtimes that don't provide a builtin.
In Vite this covers `vite build`, workers, dep optimization and the HMR
dev server (esbuild dependency bundles, `/@id/` unwrapping, worker realm
routing, core rewriting, the dev import map and the CommonJS require
shim).
nx-cloud
Bot
commented
Nov 9, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
View your CI Pipeline Execution ↗ for commit 8635dd3
| Command |
Status |
Duration |
Result |
nx test apps-automated -c=ios |
✅ Succeeded |
3m 15s |
View ↗ |
nx run-many --target=test --configuration=ci --... |
✅ Succeeded |
1s |
View ↗ |
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗
☁️ Nx Cloud last updated this comment at 2026-11-09 18:10:50 UTC
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
pkg-pr-new
Bot
commented
Nov 9, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
Open in StackBlitz
npm i https://pkg.pr.new/@nativescript/core@11626
npm i https://pkg.pr.new/@nativescript/vite@11626
npm i https://pkg.pr.new/@nativescript/webpack@11626
commit: 8635dd3
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
…ive hooks
Replace the addBuiltinModule/polyfillBuiltinModule helpers with a single
plugin per bundler, customized the way each bundler is normally
customized:
- webpack: NativeScriptBuiltinModulesPlugin, registered by name so
webpack-chain can `.tap()` its `include` list. It externalizes on the
request after `beforeResolve`, so a NormalModuleReplacementPlugin can
redirect a builtin to a polyfill or forward a bare specifier to one.
- vite: nativescriptBuiltinModules({ include }). Extra instances add
specifiers; resolve.alias handles polyfills and forwarding, since
aliases resolve before the plugin.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
Milestone
No milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|