Bug: Circular dependency in @ui5/webcomponents-base@2.22.0 breaks Node.js ESM imports
Description
A circular dependency between Runtimes.js and CustomElementsRegistry.js in @ui5/webcomponents-base@2.22.0 causes Node.js ESM imports to fail with:
SyntaxError: The requested module './Runtimes.js' does not provide an export named 'compareRuntimes'
This prevents using UI5 Web Components in Node.js environments (e.g., Mocha/Jest tests with ESM).
Affected Versions
- ✅ Works:
@ui5/webcomponents-base@2.20.4
- ❌ Broken:
@ui5/webcomponents-base@2.22.0
- ❌ Broken:
@ui5/webcomponents-base@2.22.1-rc.0
- ❌ Broken:
@ui5/webcomponents-base@2.23.0-rc.1
Environment
- Node.js: v20.19.0
- npm: 10.8.2
- OS: macOS (Darwin 25.5.0)
- Module system: ESM (
"type": "module" in package.json)
Circular Dependency Chain
Runtimes.js (line 1):
import { getAllRegisteredTags } from "./CustomElementsRegistry.js";
CustomElementsRegistry.js (line 2):
import { getCurrentRuntimeIndex, compareRuntimes, getAllRuntimes } from "./Runtimes.js";
This creates the cycle: Runtimes.js → CustomElementsRegistry.js → Runtimes.js
Why This Fails
In Node.js ESM:
- Node loads
Runtimes.js
Runtimes.js imports from CustomElementsRegistry.js
CustomElementsRegistry.js imports from Runtimes.js (which hasn't finished loading)
- Node.js can't resolve
compareRuntimes because the module isn't fully evaluated yet
- Error: "does not provide an export named 'compareRuntimes'"
Note: Bundlers like Webpack/Vite handle this fine because they analyze the entire module graph before execution. This only affects Node.js runtime.
Reproduction
- Create test project:
mkdir ui5-circular-test && cd ui5-circular-test
npm init -y
npm install @ui5/webcomponents-base@2.22.0
- Update package.json:
- Create test.mjs:
import '@ui5/webcomponents-base/dist/CustomElementsRegistry.js';
console.log('Success!');
- Run:
Expected: Script runs successfully
Actual:
SyntaxError: The requested module './Runtimes.js' does not provide an export named 'compareRuntimes'
Workaround
Downgrade to @ui5/webcomponents-base@2.20.4:
npm install @ui5/webcomponents-base@2.20.4
Suggested Fix
Break the circular dependency by:
Option 1: Extract shared utilities to a third module
RuntimesUtils.js (contains compareRuntimes, getAllRuntimes, etc.)
↑ ↑
└── Runtimes.js └── CustomElementsRegistry.js
Option 2: Use lazy/dynamic imports for one direction
// In Runtimes.js
let _getAllRegisteredTags;
const getAllRegisteredTags = () => {
if (!_getAllRegisteredTags) {
const module = await import("./CustomElementsRegistry.js");
_getAllRegisteredTags = module.getAllRegisteredTags;
}
return _getAllRegisteredTags();
};
Option 3: Refactor to eliminate the cross-dependency entirely
Impact
This blocks users from:
- Running unit tests with Mocha/Jest in ESM mode
- Using UI5 Web Components in Node.js SSR scenarios
- Any Node.js environment that imports these modules directly
Additional Info
The issue exists in all post-2.20.x versions tested. Since @ui5/webcomponents-base@2.20.4 was published on the same day as 2.22.0, this appears to be a regression introduced in the 2.22 refactoring.
Bug: Circular dependency in @ui5/webcomponents-base@2.22.0 breaks Node.js ESM imports
Description
A circular dependency between
Runtimes.jsandCustomElementsRegistry.jsin@ui5/webcomponents-base@2.22.0causes Node.js ESM imports to fail with:This prevents using UI5 Web Components in Node.js environments (e.g., Mocha/Jest tests with ESM).
Affected Versions
@ui5/webcomponents-base@2.20.4@ui5/webcomponents-base@2.22.0@ui5/webcomponents-base@2.22.1-rc.0@ui5/webcomponents-base@2.23.0-rc.1Environment
"type": "module"in package.json)Circular Dependency Chain
Runtimes.js(line 1):CustomElementsRegistry.js(line 2):This creates the cycle:
Runtimes.js→CustomElementsRegistry.js→Runtimes.jsWhy This Fails
In Node.js ESM:
Runtimes.jsRuntimes.jsimports fromCustomElementsRegistry.jsCustomElementsRegistry.jsimports fromRuntimes.js(which hasn't finished loading)compareRuntimesbecause the module isn't fully evaluated yetNote: Bundlers like Webpack/Vite handle this fine because they analyze the entire module graph before execution. This only affects Node.js runtime.
Reproduction
{ "type": "module" }Expected: Script runs successfully
Actual:
Workaround
Downgrade to
@ui5/webcomponents-base@2.20.4:Suggested Fix
Break the circular dependency by:
Option 1: Extract shared utilities to a third module
Option 2: Use lazy/dynamic imports for one direction
Option 3: Refactor to eliminate the cross-dependency entirely
Impact
This blocks users from:
Additional Info
The issue exists in all post-2.20.x versions tested. Since
@ui5/webcomponents-base@2.20.4was published on the same day as 2.22.0, this appears to be a regression introduced in the 2.22 refactoring.