2026-03-06 by Showboat
PR #846 (CDSTLZ-193-esm) migrates webbloqs to native ESM with nodenext module resolution.
Consumer repo audits revealed that @webbloqs/react has 9 flat files at src/ root
(i18n, models, validation, etc.) imported 518+ times across ewz repos — but with no
explicit barrel exports. Under strict ESM, these require .js extensions.
Two complementary fixes:
-
Barrel exports generator (
scripts/generate-barrel-exports.mjs) now auto-detects flat.tsfiles at each package'ssrc/root and generates explicitpublishConfig.exportsentries. This makes extensionless imports valid under strict ESM. -
Codemod (
packages/codemods/transforms/esm-migration/index.ts) now reads the package's exports map and skips adding.jswhen an explicit barrel entry exists — producing the shortest valid import for each specifier.
| Package | Barrel dirs | Flat files | Total exports |
|---|---|---|---|
@webbloqs/elements |
57 | 0 | 57 |
@webbloqs/react |
33 | 9 | 42 |
@webbloqs/css-runtime |
4 | 1 | 5 |
create-component, global, i18n, media, models, option, properties, tracking, validation
pnpm --filter @webbloqs/codemods test 2>&1 | grep -E "(PASS|FAIL|Tests:|Test Suites:)"PASS __tests__/esm-migration.test.ts
Test Suites: 1 passed, 1 total
Tests: 18 passed, 18 total
pnpm run test:esm 2>&1 | grep -E "^(---| |===)"--- Step 1: Building packages ---
--- Step 2: Packing tarballs ---
--- Step 3: Creating consumer project ---
--- Step 4: Testing imports via esbuild (bundler) ---
esbuild bundle: OK
--- Step 4b: Testing imports via Webpack 5 (fullySpecified) ---
Building with Webpack 5...
Webpack 5 build: OK
--- Step 4c: Testing consumer-specific import patterns ---
package.json metadata reads: OK
--- Step 5: Testing TypeScript type resolution ---
TypeScript types: OK
--- Step 6: Verifying package metadata ---
--- Step 6b: Verifying .js extensions in compiled imports ---
All relative imports have .js extensions: OK
=== ESM Smoke Test PASSED ===
All 4 consumer repos tested with updated tarballs from /tmp/webbloqs-esm-tarballs/.
The codemod now produces the shortest valid import — flat file imports with barrel exports
are left extensionless, only deep subpath imports get .js added.
| Repo | Files changed | Build | Previous run |
|---|---|---|---|
| mchweb | 5 | PASS | was 55 |
| cpq-cds | 3 | PASS (webpack) | was 119+58 |
| ewz-webportal-components | 14 | n/a (codemod only) | was 107 |
| ewz-kus-portal | 7 | n/a (codemod only) | was 60 |
| Total | 29 | was 399 |
~93% reduction in codemod-modified files. The remaining 29 files are all deep subpath
imports (e.g., @webbloqs/elements/lib/icon/spritemap → @webbloqs/elements/lib/icon/spritemap.js)
that genuinely need .js extensions.
- mchweb: Webpack client + server builds pass with ESM tarballs
- cpq-cds: Webpack build passes (
pnpm run buildexit code 0) - ewz repos: Codemod runs without errors, all transforms correct
- Zero errors across all consumer repos
Full CI (pnpm run ci) passed: 2189+ unit tests, 35 E2E tests, all builds green.
5c12057bd F!! Add flat file barrel exports to publishConfig.exports
fb7001d03 F!! Teach codemod to prefer shortest valid import via exports map
3620b3dd3 E: Expand ESM smoke test with flat file barrel imports
bbc8c59c4 B: Fix WbComponentProps type reference in ESM smoke test