Skip to content

Conversation

@davidfirst
Copy link
Member

@davidfirst davidfirst commented Aug 21, 2025

Summary

Adds Node.js v24 ESM compatibility to fix e2e test execution issues. Node.js v24 has stricter ESM/CommonJS interop than v22, requiring explicit configuration for proper module resolution.

Root Cause Analysis

When upgrading from Node.js v22 to v24, e2e tests fail with errors like:

SyntaxError: Named export 'MissingMainFile' not found. The requested module '@teambit/legacy.bit-map' is a CommonJS module, which may not support all module.exports as named exports.

This occurs because:

  1. Node.js v24's stricter ESM/CommonJS boundary: Node.js v24 enforces stricter rules for importing named exports from CommonJS modules, especially when using lazy-loaded exports via Babel's getter functions.

  2. Babel lazy-loading incompatibility: Bit uses Babel's lazy: () => true configuration which creates getter functions for exports. These getters don't work properly with Node.js v24's ESM interop when importing from CommonJS modules.

  3. Pre-compiled components: The problematic modules (@teambit/legacy.bit-map, @teambit/legacy.scope, etc.) are pre-compiled Bit components stored in node_modules, not source files compiled on-the-fly by Mocha.

Why Forcing CommonJS Mode Doesn't Work

We explored forcing CommonJS mode for tests but discovered fundamental limitations:

  • Module type determination timing: Node.js v24 determines module type (ESM vs CommonJS) before babel-register can transform the code
  • Mocha's ESM handling: Mocha loads test files as ESM modules when they have .ts extensions and are transformed by babel-register to ESM format
  • Loader hook complexity: Custom ESM loader hooks can intercept module loading but introduce significant complexity and performance overhead
  • Global impact: Solutions that force CommonJS globally break other parts of the system (like Mocha itself)

Solution: ESM Wrapper Files

Created .mjs wrapper files that provide proper ESM exports for problematic CommonJS modules:

  • components/legacy/bit-map/esm.mjs - Exports BitMap, MissingMainFile, etc.
  • components/legacy/scope/esm.mjs - Exports ScopeNotFound and 50+ other exports
  • components/legacy/consumer/esm.mjs - Exports ConsumerNotFound
  • scopes/component/tracker/esm.mjs - Exports tracking-related classes
  • scopes/component/component-issues/esm.mjs - Exports IssuesClasses
  • scopes/component/component-url/esm.mjs - Exports URL utilities

Additional Changes

  • 122+ require() → import conversions: Updated test files to use ESM imports
  • Package.json exports fields: Added proper exports configuration for dual package support
  • Lodash import fixes: Changed from destructured imports to namespace imports for compatibility

Verification

All e2e tests now pass successfully with Node.js v24.4.1:

npm run e2e-test  # ✅ All tests pass

The solution maintains tree-shaking capabilities in production while ensuring compatibility with Node.js v24's stricter module system.

- Add MainFileIsDir export to scopes/component/tracker/esm.mjs
- Create esm.mjs files for @teambit/legacy.bit-map, @teambit/legacy.scope, and @teambit/component-issues
- Convert 122+ require('chai-fs') statements to ESM imports in e2e tests
- Convert chai plugin require statements (chai-arrays, chai-string) to ESM imports
- Fix Node.js v24 stricter ESM/CommonJS interop by providing explicit named exports

Resolves compatibility issues where Node.js v24 requires explicit ESM wrappers
for CommonJS modules to expose named exports properly.
@davidfirst davidfirst marked this pull request as draft August 21, 2025 21:01
- Add missing exports to tracker module esm.mjs (AddingIndividualFiles, ParentDirTracked, PathOutsideConsumer, VersionShouldBeRemoved)
- Fix lodash named imports in e2e tests to use namespace imports compatible with Node.js v24
- Convert 'import { uniq } from lodash' to 'import * as _ from lodash'
- Convert 'import { difference } from lodash' to 'import * as _ from lodash'

All e2e tests now pass successfully with Node.js v24.4.1
@davidfirst davidfirst marked this pull request as ready for review September 2, 2025 18:30
@davidfirst davidfirst enabled auto-merge (squash) September 2, 2025 21:02
- Create scopes/component/component-url/esm.mjs to export ComponentUrl, ScopeUrl, ComponentUrlProvider, useComponentUrl
- Fixes webpack resolution error 'Can't resolve @teambit/component.modules.component-url'
- Required for proper ESM module resolution during bit build
@davidfirst davidfirst merged commit 5841503 into master Sep 9, 2025
11 checks passed
@davidfirst davidfirst deleted the fix/node-v24-esm-compatibility branch September 9, 2025 22:16
davidfirst added a commit that referenced this pull request Oct 3, 2025
This PR fixes lodash import issues in e2e tests that were causing
failures with Node.js v24 due to ESM compatibility issues with CommonJS
modules.

## Context
See #9949
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants