Configuration Diff Tool
Shakapacker includes a semantic configuration diff workflow for webpack/rspack configs via pack-config-diff.
This gives you structured, meaningful diffs instead of raw line-by-line file diffs.
Why use this instead of diff?
Traditional file diff tools are great for source code, but generated bundler configs are noisy and deeply nested.
Semantic diffing is better for this use case because it:
- Understands nested webpack/rspack configuration objects
- Supports filtering noisy sections with
--ignore-keysand--ignore-paths - Normalizes machine-specific absolute paths by default
- Supports summary, detailed, JSON, and YAML output formats
- Handles config-specific value types (functions, RegExp, Date)
Quick Start
Export configs, then diff them:
# Export all standard configs (dev/prod + client/server)
bin/shakapacker-config --doctor
# Compare development vs production client config
bin/diff-bundler-config \
--left=shakapacker-config-exports/webpack-development-client.yaml \
--right=shakapacker-config-exports/webpack-production-client.yaml
Common Workflows
1. Works in development, broken in production
bin/shakapacker-config --doctor
bin/diff-bundler-config \
--left=shakapacker-config-exports/webpack-development-client.yaml \
--right=shakapacker-config-exports/webpack-production-client.yaml \
--format=summary
2. Compare client vs server bundles
bin/shakapacker-config --doctor
bin/diff-bundler-config \
--left=shakapacker-config-exports/webpack-production-client.yaml \
--right=shakapacker-config-exports/webpack-production-server.yaml
3. Webpack to Rspack migration validation
# Export webpack state
bin/shakapacker-config --doctor
# Switch bundler
bundle exec rake shakapacker:switch_bundler rspack --install-deps
# Export rspack state
bin/shakapacker-config --doctor
# Compare two snapshots (rename or copy files as needed)
bin/diff-bundler-config \
--left=webpack-production-client.yaml \
--right=rspack-production-client.yaml \
--ignore-paths="plugins.*"
4. Capture machine-readable report for CI or PR artifacts
bin/diff-bundler-config \
--left=baseline.yaml \
--right=current.yaml \
--format=json \
--output=config-diff.json
Output Formats
# Detailed (default)
bin/diff-bundler-config --left=a.yaml --right=b.yaml --format=detailed
# Summary
bin/diff-bundler-config --left=a.yaml --right=b.yaml --format=summary
# JSON
bin/diff-bundler-config --left=a.yaml --right=b.yaml --format=json
# YAML
bin/diff-bundler-config --left=a.yaml --right=b.yaml --format=yaml
Useful Options
# Include unchanged values
--include-unchanged
# Limit recursion depth
--max-depth=5
# Ignore keys globally
--ignore-keys=timestamp,version
# Ignore paths (supports wildcards)
--ignore-paths="plugins.*,output.path"
# Disable automatic path normalization
--no-normalize-paths
Supported Input Files
- JSON (
.json) - YAML (
.yaml,.yml) - JavaScript (
.js) - TypeScript (
.ts, requirests-node)
Exit Codes
0: no differences found1: differences found2: wrapper/runtime error (module load error, invalid return code)
For CI usage, treat 1 as "configs differ" and 2 as "tool/runtime failure".
Programmatic Usage
You can use the package directly in scripts:
const { DiffEngine, DiffFormatter } = require("pack-config-diff")
const engine = new DiffEngine({
ignorePaths: ["plugins.*"]
})
const result = engine.compare(leftConfig, rightConfig, {
leftFile: "webpack.dev.js",
rightFile: "webpack.prod.js"
})
const formatter = new DiffFormatter()
console.log(formatter.formatDetailed(result))