Skip to content

fix(vite): classify minified ESM deps chunks as ESM - #11622

Merged
NathanWalker merged 1 commit into
NativeScript:mainfrom
aleclarson:fix-deps-esm-classify
Nov 9, 2026
Merged

NathanWalker merged 1 commit into
NativeScript:mainfrom
aleclarson:fix-deps-esm-classify

Conversation

@aleclarson

Copy link
Copy Markdown
Contributor

Fixes #11621

What

collectDepsModuleExportInfo in hmr/server/deps-bundle.ts classified modules with ESM_SYNTAX_RE = /^[ \t]*(?:import…|export…)/m — anchored to line starts. A minified .js chunk (const value=1;export{value as g};) fell through to collectCjsExportInfo, got opaqueCjs: true, and the served /ns/m shim emitted only export default, dropping every named export and failing startup in the host ESM linker before the app mounts.

How

  • maskJsComments(code, literals) gains a mode that also blanks string/template/regex literal interiors (delimiters and character positions preserved). Its template skip now honors ${} interpolation — a nested literal previously desynced backtick pairing and masked real code after it.
  • Classification and the export * as / export {…} / export * from scanners run on the masked copy, so mid-line ESM is found without matching look-alike text inside literals or comments. starRe was line-anchored and starAsRe required spaces around * — both shared the defect.
  • Keyword matches use an identifier/member lookbehind (?<![.$\u200c\u200d\p{ID_Continue}]), so $export identifiers and obj.import/obj.export member access cannot flip a CJS file to ESM.
  • For export * from, the from position is located on the masked copy and the specifier literal is read back from the original text at the same offset.

Test plan

  • Verified against published @nativescript/vite 8.0.20: minified .js, .mjs, export{mt as g,xx as h} after declarations, mid-line export*from, export*as ns, mid-line export default — all produce correct names and shims.
  • Verified no false positives: export/import text inside strings, templates, line/block comments, and regexes; $export identifiers; obj.import/obj.export members — all stay CJS.
  • Swept ~2,200 real node_modules files old-vs-new: the only differences were names harvested from embedded code strings (now correctly excluded) and real mid-line ESM now detected.
  • Unresolved export * from targets still return names: null (per-module serving fallback), and opaque-CJS (module.exports = ...) still returns opaqueCjs.

The deps-bundle module classifier anchored import/export syntax to line
starts, so a minified .js chunk with export{...} after statements on one
line was treated as opaque CJS and the served shim dropped every named
export, breaking startup before the app mounts. The star re-export
scanners carried the same line-start assumption.

Run classification and the export scanners on a literal-masked copy:
maskJsComments gains a mode that also blanks string/template/regex
interiors (positions preserved) and now honors template ${} nesting —
its desync previously masked real code after nested literals. Keyword
matches are guarded by an identifier/member lookbehind so $export and
obj.import/obj.export cannot flip CJS to ESM, and mid-line
export * from / export * as re-exports are followed with the specifier
read back from the original text.
@nx-cloud

nx-cloud Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 1e6c16c

Command Status Duration Result
nx test apps-automated -c=android ✅ Succeeded 3m 23s View ↗
nx run-many --target=test --configuration=ci --... ✅ Succeeded 10s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-11-08 04:28:43 UTC

@pkg-pr-new

pkg-pr-new Bot commented Nov 8, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@nativescript/core@11622
npm i https://pkg.pr.new/@nativescript/vite@11622
npm i https://pkg.pr.new/@nativescript/webpack@11622

commit: 1e6c16c

}

const ESM_SYNTAX_RE = /^[ \t]*(?:import[\s{"'*]|export[\s{*])/m;
// ESM markers can sit anywhere on a line — minified chunks emit

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those AI comments are far too long. I think it is best to limit any comment to 2/3 lines or the code will become a book to read with a few lines of code ;)
it applies to all comments

@NathanWalker
NathanWalker merged commit 68765d7 into NativeScript:main Nov 9, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ns dev: minified ESM .js chunks misclassified as CJS — deps shims lose named exports

3 participants