-
Notifications
You must be signed in to change notification settings - Fork 11.9k
Description
Description
Hi Angular Team. I am aware this is more in the realm of a support request, but this request is somewhat bespoke and really requires a response from a core team member. I am exploring migrating Cypress Component Testing support from webpack via @angular-devkit/build-angular to the newer @angular/build using esbuild/vite and have several questions. I used GPT to organize my questions below. If there is a better medium to ask this question, please let us know!
Angular Build System Migration: Questions for Angular Core Team
Overview
Cypress Component Testing currently supports Angular Component Testing applications through @cypress/webpack-dev-server, which directly integrates with @angular-devkit/build-angular's webpack configuration. As Angular has moved to the new @angular/build system (which uses Vite with esbuild), we need guidance on how to migrate our integration to support the new build system while maintaining compatibility with existing Angular projects.
Current Implementation
How Cypress Uses @angular-devkit/build-angular
Cypress currently integrates with Angular by directly importing and using webpack configuration functions from @angular-devkit/build-angular. The implementation is located in npm/webpack-dev-server/src/helpers/angularHandler.ts.
Key Integration Points
-
Direct Module Imports: We dynamically import Angular's webpack configuration utilities:
const angularCLiModules = [ '@angular-devkit/build-angular/src/utils/webpack-browser-config.js', '@angular-devkit/build-angular/src/tools/webpack/configs/common.js', '@angular-devkit/build-angular/src/tools/webpack/configs/styles.js', '@angular-devkit/core/src/index.js', ]
-
Webpack Config Generation: We use
generateBrowserWebpackConfigFromContextto generate a webpack configuration:const { config } = await generateBrowserWebpackConfigFromContext( buildOptions, context, (wco: any) => { const stylesConfig = Promise.resolve(getStylesConfig(wco)).then((config) => { // Custom modifications for Cypress return config }) return [getCommonConfig(wco), stylesConfig] }, )
-
Fake Builder Context: We create a minimal context object that mimics Angular's builder context:
const context = { target: { project: 'angular' }, workspaceRoot: projectRoot, getProjectMetadata: () => ({ root, sourceRoot, projectType: 'application' }), logger, }
-
Configuration Merging: The generated Angular webpack config is merged with Cypress-specific webpack configuration (entry points, plugins, etc.) and then used to launch
webpack-dev-server.
What This Approach Provides
- Automatic Configuration: We inherit all of Angular's webpack configuration (loaders, plugins, optimizations, etc.)
- Compatibility: Works with Angular's build options from
angular.json - Maintenance: As Angular updates its webpack config, we automatically benefit from those changes
- Customization: Users can still override the webpack config via Cypress configuration
Desired State: Migration to @angular/build
Goal
We want to migrate to using @angular/build (which uses Vite with esbuild) so that we can use @cypress/vite-dev-server instead of @cypress/webpack-dev-server for Angular component testing. This would provide:
- Performance: Vite's faster dev server and HMR
- Consistency: Align with Angular's new build system direction
- Modern Tooling: Benefit from esbuild's speed and Vite's ecosystem
Current @cypress/vite-dev-server Architecture
Our Vite dev server works by:
- Sourcing Vite from the user's project dependencies
- Resolving or accepting a Vite configuration
- Merging user config with Cypress-specific config (plugins, entry points, etc.)
- Creating and launching a Vite dev server
For reference, see npm/vite-dev-server/src/resolveConfig.ts.
Technical Challenges
Architecture Differences
-
Build System Integration:
@angular-devkit/build-angular: Exposes webpack config generation functions that we can call directly@angular/build: Uses Vite internally viaserveWithVite()but doesn't expose a way to extract just the Vite configuration
-
Builder Context Requirements:
@angular-devkit/build-angular: We can create a minimal fake context@angular/build: TheserveWithVite()function requires a fullBuilderContextfrom@angular-devkit/architect. Are we able to use a similar approach?
-
Configuration Extraction:
- In
@angular/build, the Vite configuration is created insetupServer()(seepackages/angular/build/src/builders/dev-server/vite/server.ts) - This function is internal and not exported for external use.
- The Vite server is created and managed within the builder's execution flow
- In
Key Questions
-
Is there a supported way to extract the Vite configuration that
@angular/build:dev-serverwould use, similar to how we can extract webpack config from@angular-devkit/build-angular? I'm not sure the current method is recommended, but having a way to extract the Vite config from a public interface would be extremely helpful. -
Can we reuse
setupServer()or similar functions to generate a ViteInlineConfigthat we can then merge with Cypress-specific configuration? -
Should we use the builder directly (e.g., call
executeDevServerBuilderprogrammatically) and somehow integrate it with our dev server, or is there a better approach? This would be fairly challenging for us to accomplish reliably. -
What's the recommended migration path for tools like Cypress that need to integrate with Angular's build system for component testing? Should we even be using
@angular/buildinstead of@angular-devkit/build-angularor is it recommended to use a different method? -
Are there any plans for a public API that would allow tools to programmatically get the Vite configuration that Angular would use, without having to run the full dev server builder?
Proposed Approach (Seeking Feedback)
We're considering a few potential approaches:
Option A: Extract Vite Config from Builder
- Use
@angular/build's internal functions (if accessible) to generate the Vite config - Merge with Cypress-specific config
- Create our own Vite dev server instance. The Cypress app today currently needs control over the Vite process
Option B: Use Builder with Custom Integration
- Programmatically invoke the Angular dev server builder while being able to pass specific configuration options
- Intercept or proxy the Vite server it creates via a plugin approach, which would be fairly disruptive to our process
- Integrate with Cypress's test execution flow
Questions for Angular Team
-
What is the recommended approach for tools that need to integrate with Angular's build system for component testing when using
@angular/build? -
Is there a public API or function we can use to get the Vite configuration that
@angular/buildwould generate, without running the full builder? -
Would it be feasible to export functions like
setupServer()or create a new public API for generating Vite configurations? -
Are there any examples of other tools successfully integrating with
@angular/buildfor similar use cases? -
What is the timeline for
@angular/buildbecoming the default/recommended build system, and when should tools like Cypress prioritize migration? Cypress is aware that@angular-devkit/build-angularis still supported according to the migration documentation, but know eventually webpack will be phased out for esbuild/Vite. -
Are there any compatibility concerns we should be aware of when trying to reuse Angular's Vite configuration in a different context (Cypress's dev server)?
Additional Context
- Cypress Component Testing: Allows developers to test individual Angular components in isolation
- Current Support: Works with Angular 18-20 (Angular 21 support coming soon) using webpack-based builds
- User Impact: Many Cypress users rely on Angular component testing, so a smooth migration path is important
- Repository: cypress-io/cypress
Next Steps
We're eager to collaborate with the Angular team to find the best migration path. We're open to help where possible!