Config Diff Feature: Compare webpack/rspack configs for migration and troubleshooting
Problem Statement
Developers need better tools for migrating and troubleshooting webpack/rspack configurations. Currently, there's no systematic way to:
- Understand customizations: Compare a custom webpack config against shakapacker defaults to identify what can leverage defaults vs what must remain custom
- Migrate webpack → rspack: Identify incompatibilities, required changes, and optimization opportunities
- Debug multi-environment issues: Systematically compare development vs production, client vs server configurations
- Plan migrations: Generate actionable checklists for moving from custom webpack to shakapacker + optional rspack
Use Cases
1. Legacy webpack → shakapacker migration
Scenario: Project has heavily customized webpack config
Need: Identify which customizations are already handled by shakapacker defaults
Benefit: Layer customizations on top of shakapacker defaults instead of maintaining entire config
2. webpack → rspack conversion
Scenario: Upgrade to rspack for faster builds
Need: Identify webpack-specific plugins/loaders incompatible with rspack
Benefit: Clear migration path with automated suggestions for equivalents
3. Combined migration
Scenario: Custom webpack → shakapacker + rspack
Need: Layer both transformations systematically
Benefit: Confidence in multi-stage migration plan
4. Multi-environment debugging
Scenario: Production builds work but development doesn't (or vice versa)
Need: Systematic diff of dev vs prod configs
Benefit: Quickly identify environment-specific differences causing issues
Phased Implementation
This feature will be implemented across 5 incremental PRs, each delivering standalone value.
Phase 1: Core Diff Engine (PR #1)
Goal: Basic infrastructure for comparing two config files
New Modules:
package/configExporter/configDiffer.ts - Deep object diff algorithm
package/configExporter/pathNormalizer.ts - Normalize comparable values
package/configExporter/diffTypes.ts - TypeScript interfaces
CLI Additions:
bin/export-bundler-config --compare baseline.yaml current.yaml
bin/export-bundler-config --compare old.yaml new.yaml --diff-format=json|yaml|summary
bin/export-bundler-config --compare old.yaml new.yaml --ignore-path=output.path --ignore-path=devtool
Features:
- Deep object comparison with path tracking (e.g.,
module.rules[0].test)
- Handle arrays with ordered comparison
- Detect added/modified/removed keys
- Normalize absolute paths to relative
- Strip machine-specific values (timestamps, temp dirs)
- Ignore comments and formatting differences
Output Formats:
- JSON: Machine-readable structured diff
- Annotated YAML: Human-readable with inline change markers
- Summary: Quick overview of changes
Example Output (summary format):
Configuration Comparison
========================
Baseline: webpack-dev-client.yaml
Current: webpack-dev-client-customized.yaml
Summary: 12 additions, 3 modifications, 0 removals
Added:
- entry.admin_bundle
- module.rules[3] (TypeScript loader)
- module.rules[4] (CSS modules)
- output.publicPath
+ 8 more...
Modified:
- devtool: cheap-module-source-map → eval-source-map
- module.rules[0].test: /\.js$/ → /\.(js|jsx|ts|tsx)$/
- module.rules[0].use[0].options (added presets)
See detailed diff in: diff-output.yaml
Success Criteria:
- ✅ Compare any two webpack/rspack YAML configs
- ✅ Accurate path-level granularity
- ✅ Handle nested objects, arrays, primitives
- ✅ Normalize paths and ignore formatting
Phase 2: Baseline Generation (PR #2)
Goal: Generate reference configs on-demand via presets
New Modules:
package/configExporter/baselineGenerator.ts - Generate clean baselines
package/configExporter/presetConfig.ts - Preset definitions
lib/templates/presets/*.yaml - Preset specifications
Preset Definitions:
Each preset is a YAML specification:
# lib/templates/presets/react_on_rails.yaml
name: react_on_rails
description: Shakapacker with react_on_rails gem defaults
shakapacker_version: ">=9.0"
react_on_rails_version: ">=16.0"
required_gems:
- shakapacker
- react_on_rails
required_packages:
- webpack
- webpack-cli
- react
- react-dom
config_overrides:
javascript_transpiler: babel
CLI Additions:
bin/export-bundler-config --generate-baseline --preset=basic
bin/export-bundler-config --generate-baseline --preset=react_on_rails --bundler=rspack
bin/export-bundler-config --generate-baseline --preset=typescript --cache-dir=./baselines
Baseline Generation Process:
- Create temporary directory
- Initialize minimal Rails app
- Install specified gems/packages from preset
- Run
bin/export-bundler-config for all 4 environments (dev/prod × client/server)
- Save to cache directory (e.g.,
tmp/baselines/react_on_rails-v9.0/)
- Return paths to generated configs
Built-in Presets:
basic - Vanilla shakapacker, no frameworks
react_on_rails - Shakapacker + react_on_rails defaults
typescript - Shakapacker + TypeScript support
vue - Shakapacker + Vue.js (future)
- More can be added by community
Success Criteria:
- ✅ Generate clean baseline configs for all presets
- ✅ Baselines cached and reusable
- ✅ Support both webpack and rspack
- ✅ Generate all 4 environment combinations
Phase 3: Integrated Workflow (PR #3)
Goal: Seamless "export + diff" in one command
CLI Additions:
# Diff current config against baseline preset
bin/export-bundler-config --diff --preset=react_on_rails
# Use custom baseline directory
bin/export-bundler-config --diff --baseline-dir=./my-baselines
# Add diff to doctor output
bin/export-bundler-config --doctor --show-diff
Workflow:
- Auto-detect current project configuration (gems, packages)
- Generate or load matching baseline
- Export current configs (all 4 environments)
- Perform diffs
- Generate comprehensive report directory
Output Structure:
config-diff-report-2025-10-08/
├── baseline/
│ ├── webpack-dev-client.yaml
│ ├── webpack-dev-server.yaml
│ ├── webpack-prod-client.yaml
│ └── webpack-prod-server.yaml
├── current/
│ ├── webpack-dev-client.yaml
│ ├── webpack-dev-server.yaml
│ ├── webpack-prod-client.yaml
│ └── webpack-prod-server.yaml
├── diff/
│ ├── dev-client.diff.yaml
│ ├── dev-server.diff.yaml
│ ├── prod-client.diff.yaml
│ └── prod-server.diff.yaml
└── summary.md # Human-readable report
Summary Report (summary.md):
# Configuration Comparison Report
**Baseline**: shakapacker 9.0 + react_on_rails 16.0
**Current**: my-rails-app
**Generated**: 2025-10-08 19:54:00 UTC
## Summary
| Config | Added | Modified | Removed |
|--------|-------|----------|---------|
| dev-client | 12 | 3 | 0 |
| dev-server | 8 | 2 | 0 |
| prod-client | 15 | 5 | 1 |
| prod-server | 10 | 4 | 0 |
## Key Differences
See detailed diffs in `diff/` directory.
Success Criteria:
- ✅ Single command exports + diffs all 4 environments
- ✅ Comprehensive report suitable for code review
- ✅ Suitable for migration planning and documentation
Phase 4: Semantic Analysis (PR #4)
Goal: Intelligent interpretation of configuration differences
New Modules:
package/configExporter/semanticAnalyzer.ts - Categorize changes
package/configExporter/impactAssessor.ts - Assess impact levels
Enhanced Diff Structure:
interface DiffChange {
// Existing fields...
category: 'loader' | 'plugin' | 'optimization' | 'entry' | 'output' | 'other'
impact: 'breaking' | 'high' | 'medium' | 'low'
explanation?: string // From configDocs.ts
requiredDeps?: string[] // npm packages needed
migration?: string // Steps for breaking changes
}
CLI Additions:
# Configurable analysis depth
bin/export-bundler-config --diff --analysis=structural # Level 1: Basic diff
bin/export-bundler-config --diff --analysis=categorized # Level 2: Group by feature
bin/export-bundler-config --diff --analysis=semantic # Level 3: With explanations
bin/export-bundler-config --diff --analysis=migration # Level 4: Breaking change guidance
Semantic Categories:
- Loaders: Changes to
module.rules[].use[]
- Plugins: Changes to
plugins[]
- Entry Points: Changes to
entry.*
- Output: Changes to
output.*
- Optimization: Changes to
optimization.*
- Dev Server: Changes to
devServer.*
Impact Assessment:
- Breaking: Removes functionality, app won't build/run
- High: Affects core functionality, requires code changes
- Medium: Feature additions, optional changes
- Low: Config tweaks, no functional impact
Enhanced Report Example:
## High-Impact Changes (dev-client)
### ⚠️ BREAKING: Removed Entry Point
- **Path**: `entry.legacy_bundle`
- **Impact**: Application code will not be bundled
- **Action**: Restore entry point or remove references
### 🔧 TypeScript Loader Added
- **Path**: `module.rules[3]`
- **Category**: Loader
- **Impact**: Medium
- **Dependencies**: `ts-loader`, `typescript`
- **Install**: `npm install --save-dev ts-loader typescript`
- **Docs**: https://shakapacker.dev/docs/typescript
### 📦 CSS Modules Configuration
- **Path**: `module.rules[1].use[1].options.modules`
- **Impact**: Medium
- **Changes**:
- `namedExport`: false → true
- `exportLocalsConvention`: 'asIs' → 'camelCaseOnly'
- **Migration**: Update imports from `styles['class-name']` to `styles.className`
Success Criteria:
- ✅ Categorized diffs (loaders, plugins, etc)
- ✅ Impact levels (breaking, high, medium, low)
- ✅ Links to configDocs explanations
- ✅ Required dependencies detected and listed
- ✅ Breaking changes flagged with migration guidance
Phase 5: webpack→rspack Migration (PR #5)
Goal: Specialized support for webpack → rspack conversion
New Modules:
package/configExporter/rspackMigration.ts - Migration logic
package/configExporter/compatibilityChecker.ts - Detect incompatibilities
CLI Additions:
# Analyze webpack → rspack migration
bin/export-bundler-config --migrate-to-rspack
# Compare webpack vs rspack configs
bin/export-bundler-config --diff --from=webpack --to=rspack
# Dry run: Show what would change
bin/export-bundler-config --migrate-to-rspack --dry-run
# Apply automated migrations
bin/export-bundler-config --migrate-to-rspack --apply
# Keep both configs for comparison
bin/export-bundler-config --migrate-to-rspack --keep-both
Compatibility Detection:
interface CompatibilityIssue {
path: string
issue: 'incompatible' | 'deprecated' | 'suboptimal'
webpack: any
rspack: any | null // null if no direct equivalent
migration: string
automated: boolean // Can be auto-fixed?
}
Known Migration Patterns:
MiniCssExtractPlugin → Built-in CSS extraction (experiments.css: true)
ForkTsCheckerWebpackPlugin → Built-in type checking
babel-loader → Optional builtin:swc-loader (20x faster)
DefinePlugin → Same API (no changes needed)
- Custom plugins → Manual review required
Migration Report Example:
# Webpack → Rspack Migration Analysis
## Compatibility Summary
- ✅ Compatible: 45 settings
- 🔄 Requires Changes: 8 settings
- ⚠️ Manual Review: 3 settings
- 🚀 Optimization Opportunities: 6 settings
## Required Changes
### 1. CSS Extraction (Automated ✓)
**Current**: Using `MiniCssExtractPlugin`
**Rspack**: Built-in CSS extraction
**Action**: Remove plugin, add `experiments: { css: true }`
**Script**: `bin/export-bundler-config --migrate-to-rspack --apply`
### 2. TypeScript Type Checking (Automated ✓)
**Current**: Using `ForkTsCheckerWebpackPlugin`
**Rspack**: Built-in type checking
**Action**: Remove plugin
## Optimization Opportunities
### 🚀 Switch to Built-in SWC (Optional)
**Current**: Using `babel-loader`
**Rspack**: Built-in SWC (20x faster)
**Benefit**: Significantly faster builds
**Trade-off**: Some Babel plugins may lack SWC equivalents
## Manual Review Required
### Custom Plugin: `MyCustomPlugin`
**Status**: No known rspack equivalent
**Action**: Review source, may need rspack rewrite
**Docs**: https://rspack.dev/api/plugins
Success Criteria:
- ✅ Detect webpack-specific features
- ✅ Suggest rspack equivalents with steps
- ✅ Identify optimization opportunities
- ✅ Auto-apply safe migrations with
--apply
- ✅ Generate comprehensive migration checklist
Technical Design Decisions
Cross-Version Comparison
- Major version matching: Default behavior matches baselines by major version
- Allow cross-version: Flag warnings when comparing across major versions
- Use case: Planning v8 → v9 upgrades
Path Normalization
- Absolute paths: Converted to relative for comparison
- Machine-specific values: Stripped (timestamps, temp dirs, user paths)
- Ignore patterns: Configurable via
--ignore-path flag
Baseline Strategy
- Dynamic generation: Create baselines on-demand via presets
- Caching: Cache baselines for reuse (configurable directory)
- Versioning: Baselines tied to shakapacker major version
- Community presets: Allow custom preset definitions
Multi-Environment Support
All features work across 4 config combinations:
- Development × Client
- Development × Server
- Production × Client
- Production × Server
Incremental Delivery
- Each phase delivers standalone value
- PRs are independently reviewable
- No breaking changes to existing functionality
- Backward compatible with current
--doctor mode
Open Questions / Future Enhancements
Community Contributions
- Should presets live in separate repo for community contributions?
- How to version/maintain community presets?
Integration Points
- Should
--doctor automatically include diff against standard baseline?
- Integration with CI/CD for config drift detection?
- VS Code extension for visual diff?
Advanced Features (Post v1.0)
- Interactive diff mode with accept/reject changes
- Config migration scripts (auto-apply changes)
- Diff history tracking (track config evolution over time)
- AI-powered migration suggestions
Success Metrics
Phase 1 Success
- Developers can compare any two configs
- Produces accurate structural diffs
- Handles all config types (webpack, rspack, dev, prod)
Phase 2 Success
- Baselines available for common setups
- Community can define custom presets
- Baselines cached for performance
Phase 3 Success
- Single command workflow adoption
- Reports used in code reviews and documentation
Phase 4 Success
- Semantic analysis reduces troubleshooting time
- Breaking changes clearly identified
- Required dependencies auto-detected
Phase 5 Success
- Successful webpack → rspack migrations
- Auto-migration adoption rate
- Reduction in migration-related issues
Implementation Timeline
| Phase |
Estimated Effort |
Depends On |
| Phase 1 |
1-2 weeks |
Current PR #647 merged |
| Phase 2 |
2-3 weeks |
Phase 1 merged |
| Phase 3 |
1-2 weeks |
Phase 2 merged |
| Phase 4 |
2-3 weeks |
Phase 3 merged |
| Phase 5 |
2-3 weeks |
Phase 4 merged |
Total: ~10-15 weeks for complete implementation
Related Issues / PRs
Labels
enhancement config-exporter multi-phase help wanted good first issue (Phase 1)
Config Diff Feature: Compare webpack/rspack configs for migration and troubleshooting
Problem Statement
Developers need better tools for migrating and troubleshooting webpack/rspack configurations. Currently, there's no systematic way to:
Use Cases
1. Legacy webpack → shakapacker migration
Scenario: Project has heavily customized webpack config
Need: Identify which customizations are already handled by shakapacker defaults
Benefit: Layer customizations on top of shakapacker defaults instead of maintaining entire config
2. webpack → rspack conversion
Scenario: Upgrade to rspack for faster builds
Need: Identify webpack-specific plugins/loaders incompatible with rspack
Benefit: Clear migration path with automated suggestions for equivalents
3. Combined migration
Scenario: Custom webpack → shakapacker + rspack
Need: Layer both transformations systematically
Benefit: Confidence in multi-stage migration plan
4. Multi-environment debugging
Scenario: Production builds work but development doesn't (or vice versa)
Need: Systematic diff of dev vs prod configs
Benefit: Quickly identify environment-specific differences causing issues
Phased Implementation
This feature will be implemented across 5 incremental PRs, each delivering standalone value.
Phase 1: Core Diff Engine (PR #1)
Goal: Basic infrastructure for comparing two config files
New Modules:
package/configExporter/configDiffer.ts- Deep object diff algorithmpackage/configExporter/pathNormalizer.ts- Normalize comparable valuespackage/configExporter/diffTypes.ts- TypeScript interfacesCLI Additions:
Features:
module.rules[0].test)Output Formats:
Example Output (summary format):
Success Criteria:
Phase 2: Baseline Generation (PR #2)
Goal: Generate reference configs on-demand via presets
New Modules:
package/configExporter/baselineGenerator.ts- Generate clean baselinespackage/configExporter/presetConfig.ts- Preset definitionslib/templates/presets/*.yaml- Preset specificationsPreset Definitions:
Each preset is a YAML specification:
CLI Additions:
Baseline Generation Process:
bin/export-bundler-configfor all 4 environments (dev/prod × client/server)tmp/baselines/react_on_rails-v9.0/)Built-in Presets:
basic- Vanilla shakapacker, no frameworksreact_on_rails- Shakapacker + react_on_rails defaultstypescript- Shakapacker + TypeScript supportvue- Shakapacker + Vue.js (future)Success Criteria:
Phase 3: Integrated Workflow (PR #3)
Goal: Seamless "export + diff" in one command
CLI Additions:
Workflow:
Output Structure:
Summary Report (
summary.md):Success Criteria:
Phase 4: Semantic Analysis (PR #4)
Goal: Intelligent interpretation of configuration differences
New Modules:
package/configExporter/semanticAnalyzer.ts- Categorize changespackage/configExporter/impactAssessor.ts- Assess impact levelsEnhanced Diff Structure:
CLI Additions:
Semantic Categories:
module.rules[].use[]plugins[]entry.*output.*optimization.*devServer.*Impact Assessment:
Enhanced Report Example:
Success Criteria:
Phase 5: webpack→rspack Migration (PR #5)
Goal: Specialized support for webpack → rspack conversion
New Modules:
package/configExporter/rspackMigration.ts- Migration logicpackage/configExporter/compatibilityChecker.ts- Detect incompatibilitiesCLI Additions:
Compatibility Detection:
Known Migration Patterns:
MiniCssExtractPlugin→ Built-in CSS extraction (experiments.css: true)ForkTsCheckerWebpackPlugin→ Built-in type checkingbabel-loader→ Optionalbuiltin:swc-loader(20x faster)DefinePlugin→ Same API (no changes needed)Migration Report Example:
Success Criteria:
--applyTechnical Design Decisions
Cross-Version Comparison
Path Normalization
--ignore-pathflagBaseline Strategy
Multi-Environment Support
All features work across 4 config combinations:
Incremental Delivery
--doctormodeOpen Questions / Future Enhancements
Community Contributions
Integration Points
--doctorautomatically include diff against standard baseline?Advanced Features (Post v1.0)
Success Metrics
Phase 1 Success
Phase 2 Success
Phase 3 Success
Phase 4 Success
Phase 5 Success
Implementation Timeline
Total: ~10-15 weeks for complete implementation
Related Issues / PRs
configDocs.tsdocumentation system--doctormode troubleshooting capabilitiesLabels
enhancementconfig-exportermulti-phasehelp wantedgood first issue(Phase 1)