Skip to content

fix(schematics): ship shared util chunks and load the build as CommonJS (#DS-5799) - #2262

Open
lskramarov wants to merge 2 commits into
mainfrom
fix/DS-5799
Open

lskramarov wants to merge 2 commits into
mainfrom
fix/DS-5799

Conversation

@lskramarov

@lskramarov lskramarov commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Both ng add @koobiq/components and ng update to 21 are broken in the published 21.0.0: the schematics in dist/components/schematics fail to load, for two independent reasons.

  1. Shared chunks are not shipped. Rollup puts every util imported by several entries without an entry of its own into a hashed chunk at the root of packages/schematics/dist (package-config-*.js, replacement-driver-*.js, signal-members-migration-*.js, …). copy-meta-to-dist.js copies only ng-add/, migrations/ and utils/, so ng-add, two util facades and all 88 migrations require a file that is not in the package (MODULE_NOT_FOUND).
  2. CommonJS in an ESM package. ng-packagr 21 writes "type": "module" into dist/components/package.json (packageJson.type ??= 'module'). The schematics are CommonJS .js, so Node loads them as ES modules and fails with exports is not defined in ES module scope. This error hides the first one: fixing only the module type still leaves MODULE_NOT_FOUND.

List of notable changes:

  • updated rollup.config.js: the build emits .cjs, which Node loads as CommonJS whatever the package type (as @angular/core ships its schematics). Every src/utils/*.ts except specs, .d.ts and testing.ts is an entry of its own; any other module shared by several entries goes into utils/[name]-[hash].cjs. The build fails when shipped code imports test tooling (vitest, */testing).
  • updated copy-meta-to-dist.js: starts from an empty dist/components/schematics, copies the .cjs modules and writes collection.json / migrations.json with .cjs factories (require.resolve() does not try .cjs; the sources stay extension-less for the specs).
  • added scripts/check-dist.mjs, run at the end of build:schematics: no .js module ships; every require() / import() (read from the syntax tree) names a file of the package or a package consumers have — non-optional peers, tslib, @angular-devkit/schematics, @schematics/angular, @angular/compiler, typescript — and resolves, import() with the ESM conditions; the collections are found through the manifest's schematics and ng-update.migrations, every factory loads with a plain require() (as ExportStringRef does) and exports a function, every schema parses.
  • updated tools/check-npm-resolution: packs with --json and fails when the tarball leaves out a file of schematics/.

What should reviewers focus on?

  • build:schematics relies on build:components having run first (the copy step writes into dist/components); build-packages already runs them in that order.
  • Verified: the check fails on each regression put back (a .js module, a package consumers lack, a missing util, a factory-less entry, a broken schema); require('…') inside strings and comments is ignored; a stale migration directory is removed by the copy step; rollup rejects a util that imports @angular-devkit/schematics/testing and ignores a .d.ts; a module shared by two migrations ships as utils/<name>-<hash>.cjs; check-npm-resolution fails when .npmignore drops a schematics file. A tarball from npm pack of the fixed dist/components runs ng-add and all 82 ng update migrations through SchematicTestRunner; the published 21.0.0 fails on every one.
  • 20.4.x, 20.3.x, 19.x and 18.x are not affected (ng-packagr < 21 sets no type, and every util there has an entry), so there are no backports.
  • The 21.0.0 release needs a follow-up patch release.

…JS (#DS-5799)

Rollup put the utils shared by several entries into hashed chunks at the root of
packages/schematics/dist, which copy-meta-to-dist.js does not ship: ng-add and every
migration failed with MODULE_NOT_FOUND. Every src/utils module is now a rollup entry.

ng-packagr 21 writes "type": "module" into dist/components/package.json, so Node loaded
the CommonJS schematics as ES modules ("exports is not defined in ES module scope"). The
build now ships schematics/package.json with "type": "commonjs" and re-includes it in the
.npmignore that ng-packagr writes to drop nested manifests.

build:schematics ends with check-dist.js: every require() and import() of the shipped
files resolves, every collection factory loads, and npm pack keeps every file.
@lskramarov lskramarov self-assigned this Oct 27, 2026
@github-actions github-actions Bot added the bug Something isn't working label Oct 27, 2026
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Visit the preview URL for this PR (updated for commit 8443fe5):

https://koobiq-next--prs-2262-d8zqm75w.web.app

(expires Fri, 30 Oct 2026 18:57:44 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: c9e37e518febda70d0317d07e8ceb35ac43c534c

…onsumers load them (#DS-5799)

The build emits .cjs, which stays CommonJS whatever the package type, so the nested manifest and
the .npmignore rule that re-included it are gone; the shipped collections point at .cjs factories.
A module shared by several entries goes into utils/, which ships whole. Util entries skip .d.ts,
and the build fails when shipped code imports test tooling. The copy step starts from an empty
schematics directory, so a removed migration does not stay in the package.

check-dist.mjs reads require() and import() from the syntax tree, resolves import() with the ESM
conditions, accepts only packages that consumers have, rejects .js modules, follows the manifest
fields to the collections and checks schemas and factory-less entries. The npm pack check moves
to check-npm-resolution, which already packs the package and prints npm's output on failure.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant