Skip to main content

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.

Use this during webpack-to-Rspack migrations whenever you need to confirm that a generated or hand-rolled rspack config preserved the important behavior of the old webpack config. It is especially useful before deleting a custom webpack builder, changing SSR/client split configs, or replacing plugin chains.

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-keys and --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.yml \
--right=shakapacker-config-exports/webpack-production-client.yml

Common Workflows

1. Works in development, broken in production

bin/shakapacker-config --doctor

bin/diff-bundler-config \
--left=shakapacker-config-exports/webpack-development-client.yml \
--right=shakapacker-config-exports/webpack-production-client.yml \
--format=summary

2. Compare client vs server bundles

bin/shakapacker-config --doctor

bin/diff-bundler-config \
--left=shakapacker-config-exports/webpack-production-client.yml \
--right=shakapacker-config-exports/webpack-production-server.yml

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.yml \
--right=rspack-production-client.yml \
--ignore-paths="plugins.*"

Run this comparison for each important build target, such as development client, production client, and SSR/server bundles. Start with --format=summary, then rerun without it for detailed paths when the summary shows a behavioral difference you did not expect.

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, requires ts-node)

Exit Codes

  • 0: no differences found
  • 1: differences found
  • 2: 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))

See Also