-
-
Notifications
You must be signed in to change notification settings - Fork 282
Description
📖 Description
We want to transition AnalogJS v2.0.0-alpha to ECMAScript Modules (ESM) as the default module format. This unlocks better build optimization, aligns with Vite and Angular’s future direction, and removes legacy CommonJS (CJS) constraints.
However, Angular 17+ builders and parts of the ecosystem still rely on CommonJS-only dependencies, which could introduce compatibility issues if we go fully ESM without a transition plan. This issue kicks off the discussion around how to adopt ESM safely, while maintaining compatibility with Angular’s build system and avoiding unnecessary breakage for downstream consumers.
⚠️ Problem Areas
-
Angular Constraints
Angular 17+ supports ESM via esbuild/Webpack, but some internal builders and third-party deps remain CJS, leading to build warnings or outright errors.
➡️ See: Angular CLI Build System Migration -
Dependency Landscape
Non-ESM-compatible dependencies trigger CommonJS warnings, reduce tree-shaking, and hurt build optimization. -
Downstream Consumption
If@analogjs/*
packages are published as ESM-only, any consumer still using CJS (require('@analogjs/...')
) will break withERR_REQUIRE_ESM
.- ✅ Vite-based apps: no problem (already ESM-first).
- ✅ Node SSR (Nitro/Angular Universal) on Node 18+: safe with
"type": "module"
. - ❌ Legacy CJS tooling (Jest without ESM setup, schematics, ts-node scripts): will break.
-
Collaboration & Planning
Large shifts like this need alignment up front to prevent wasted effort (e.g., PRs landing before consensus).
💡 Proposed Solutions
-
Phased ESM Rollout
- Identify and upgrade ESM-compatible dependencies.
- Keep CJS fallback for Angular builder–tied deps.
- Update internal imports to comply with
"exports"
/bundler-style resolution.
-
Experimental ESM Branch
- Maintain a separate
alpha-esm
branch to test the full switch. - CI matrix (Linux/Windows, Node 18/20/22) to surface environment-specific breakage early.
- Maintain a separate
-
Dual Output Strategy (Optional)
- For sensitive entry points (builders, schematics, CLI hooks), consider shipping dual builds (ESM + CJS) temporarily.
- This softens the transition for downstreams still on CJS.
-
Community Alignment
- Use issues (like this) to discuss breaking changes before PRs.
- Document migration steps clearly (
"type": "module"
,await import()
, updating Jest configs).
❓ Open Questions
- Which Angular 17+ dependencies are still blocking ESM adoption?
- Do we want to go ESM-only in alpha (fast clean break) or dual-build for a few cycles?
- What’s the minimum Node/TypeScript baseline we enforce for v2-alpha?
- How should we update
create-analog
templates to reflect the ESM-first approach?
✅ Next Steps
- Audit Angular 17+ CommonJS dependencies.
- Test full ESM builds in a separate branch.
- Verify compatibility in downstream contexts (SSR, Storybook, Vitest, Jest).
- Gather community feedback before finalizing release strategy.
- Update templates, docs, and migration guides.
🔗 References
- Angular CLI Build System Migration
- PR #1839 – refactor(platform): migrate to moduleResolution bundler
📝 Notes
This issue starts the collaborative planning for AnalogJS's ESM transition. Please share your thoughts:
- Any known blockers in your projects?
- Strong opinions on ESM-only vs dual-build for alpha?
- Tooling setups (Jest, schematics, SSR) we should prioritize testing against?
Updated Argument
After diving deeper into our codebase, here's the concrete technical debt that strengthens the case for ESM migration:
🔍 Current State Analysis
Measurable CommonJS Technical Debt
- 33 CommonJS
require()
statements across 16 files in our codebase - 15+ packages manually excluded from optimization in
deps-plugin.ts
(@angular/platform-server
,@nx/angular
,webpack
, etc.) specifically because they use CommonJS - Dual dependency conflicts: We currently ship both
@angular-devkit/build-angular
(CommonJS) AND@angular/build
(ESM) as dependencies
Specific Performance Pain Points
- Vite pre-bundling overhead: Our
optimizeDeps.exclude
list forces manual dependency management instead of automatic bundler optimization - Build optimizer limitations: Our
angular-build-optimizer-plugin.ts
detects Angular packages via/fesm20/
patterns because CommonJS prevents better static analysis - SSR complexity: Files like
ssr-build-plugin.ts
contain manualglobal.
→globalThis.
replacements that exist only due to CommonJS/ESM interop issues - Development friction: Hot reload performance suffers in our 963-line
angular-vite-plugin.ts
when mixing module systems
🎯 Concrete Migration Benefits
Current CommonJS Pain | ESM Solution | AnalogJS Benefit |
---|---|---|
33 require() statements |
Native import |
Faster dev server, better HMR |
Manual 15+ package exclusions | Automatic optimization | Simpler deps-plugin.ts |
Dual @angular-devkit + @angular/build deps |
Single @angular/build ESM |
Cleaner dependency tree |
/fesm20/ pattern detection |
Static ESM analysis | Better build optimizer |
global → globalThis patches |
Native ESM globals | Cleaner SSR plugins |
🚀 Strategic Positioning
Angular's ESM Leadership Opportunity
- Current transition state: AnalogJS templates use Angular 19+ with both legacy and modern build packages, showing we're already in the ecosystem's transition period
- Validation opportunity: Angular 18+ introduced
@angular/build/private
ESM exports, but the community needs frameworks like AnalogJS to validate real-world usage - Vite-native advantage: We already have esbuild integration, making us perfectly positioned to benefit immediately from ESM optimizations
Phased Implementation Strategy
- Critical path: Target
packages/vite-plugin-angular/src/lib/utils/devkit.ts
first - migrate fromrequire('@angular-devkit/build-angular')
toimport('@angular/build/private')
- Plugin modernization: Incrementally update
deps-plugin.ts
,platform-plugin.ts
, androuter-plugin.ts
- Performance benchmarking: Measure build times before/after to quantify improvements
- Testing ecosystem: Evaluate Jest 30 (improved ESM support) or recommend Vitest for ESM-native testing
This data-driven approach shows AnalogJS has specific, measurable technical debt that ESM migration directly resolves - not just theoretical future benefits, but immediate improvements to our existing plugin architecture and build optimization systems.