Skip to content

Add support for Rspack #1389

@Kocal

Description

@Kocal

Related to symfony/symfony#59707

The plan generated by Claude Opus 4.5 after some discussions, and may evolve in the future.

Plan: Experimental Rspack Support in Webpack Encore

Allow users to use rspack as an alternative to webpack via Encore.enableRspack(). Rspack is a webpack-compatible bundler written in Rust, offering significantly better performance.

Caution

Before starting anything, web-infra-dev/rspack#12682 must be solved.


Phase 1: Base Infrastructure

  • 1.1 Update package.json: make webpack, webpack-cli, webpack-dev-server optional via peerDependenciesMeta
  • 1.2 Add @rspack/core, @rspack/cli, @rspack/dev-server as optional peerDependencies
  • 1.3 Create a helper lib/utils/bundler.js exposing:
    • isWebpackInstalled(): checks if webpack and webpack-cli are present
    • isRspackInstalled(): checks if @rspack/core and @rspack/cli are present
    • getBundlerModule(): returns require('webpack') or require('@rspack/core') based on context
  • 1.4 Update encore.js: on startup, verify at least one bundler is installed. Clear error otherwise: "Neither webpack nor @rspack/core is installed. Please install one: npm install webpack webpack-cli --save-dev"

Phase 2: Public API enableRspack()

  • 2.1 Add useRspack = false flag in WebpackConfig.js
  • 2.2 Add enableRspack() method in WebpackConfig.js:
    • Sets useRspack flag to true
    • Displays console warning [EXPERIMENTAL] Rspack support is experimental and may not work with all features
  • 2.3 Expose enableRspack() in index.js via the Encore proxy
  • 2.4 Update encore.js: if useRspack is enabled but rspack is not installed, throw explicit error. Same if rspack is enabled but webpack-dev-server is used without @rspack/dev-server

Phase 3: Dynamic Bundler CLI Switch

  • 3.1 Update encore.js: dynamically switch between CLIs based on useRspack
    • webpack/bin/webpack@rspack/cli
    • webpack-dev-server/bin/webpack-dev-server@rspack/dev-server
  • 3.2 Adapt console messages: "Running rspack..." vs "Running webpack..."
  • 3.3 Update showUsageInstructions() to mention rspack if installed

Phase 4: Config Generator Adaptation

  • 4.1 Update config-generator.js: dynamically import the bundler module via the getBundlerModule() helper
  • 4.2 Adapt native plugin imports: DefinePlugin, ProvidePlugin, HotModuleReplacementPlugin from webpack or @rspack/core
  • 4.3 Handle stats configuration differences between webpack and rspack

Phase 5: Plugin Adaptation

  • 5.1 mini-css-extract.js: use CssExtractRspackPlugin (builtin) if rspack, otherwise MiniCssExtractPlugin
  • 5.2 terser.js: use SwcJsMinimizerRspackPlugin (builtin) if rspack, otherwise TerserWebpackPlugin
  • 5.3 css-minimizer.js: use LightningCssMinimizerRspackPlugin (builtin) if rspack, otherwise CssMinimizerPlugin
  • 5.4 define.js: import DefinePlugin from the correct module
  • 5.5 variable-provider.js: import ProvidePlugin from the correct module
  • 5.6 friendly-errors.js: disable if rspack (return null), rspack has its own error reporting system via stats

Phase 6: Loader Adaptation

  • 6.1 css.js: adapt import of MiniCssExtractPlugin.loader vs rspack builtin loader
  • 6.2 [CRITICAL] Rewrite copy-files-loader.js: remove usage of webpack/lib/dependencies/LoaderDependency (internal API incompatible with rspack). Possible alternatives:
    • Use native asset modules
    • Use rspack.CopyPlugin / copy-webpack-plugin
  • 6.3 Verify compatibility of other loaders with rspack (most should work out of the box)

Phase 7: Custom Encore Plugin Adaptation

  • 7.1 delete-unused-entries-js-plugin.js: verify compatibility of hooks compiler.hooks.compilation and compilation.hooks.additionalAssets with rspack
  • 7.2 entry-points-plugin.js: verify compatibility of hook compiler.hooks.afterEmit
  • 7.3 asset-output-display.js: verify compatibility of hook compiler.hooks.emit

Phase 8: features.js Update

  • 8.1 Add rspack feature in features.js with required packages: @rspack/core, @rspack/cli
  • 8.2 Add rspack-dev-server feature with package @rspack/dev-server
  • 8.3 Adapt error messages to guide users toward installing the correct bundler

Phase 9: Tests

  • 9.1 Create test_apps/rspack/: minimal test application with rspack
  • 9.2 Create test_apps/rspack-with-babel/: test with babel-loader
  • 9.3 Adapt unit tests to cover both bundlers (parameterized)
  • 9.4 Adapt functional.js to run tests with rspack
  • 9.5 Configure CI (GitHub Actions) with matrix: bundler: [webpack, rspack]

Phase 10: Documentation

  • 10.1 Update README.md: add section "Experimental: Using Rspack"
    • Explain benefits (performance)
    • Installation: npm install @rspack/core @rspack/cli @rspack/dev-server --save-dev
    • Activation: Encore.enableRspack()
    • Known limitations
  • 10.2 Document features not supported with rspack (if any)
  • 10.3 Update CHANGELOG.md

Out of Scope (v1) / Future Improvements

  • handlebars-loader support with rspack (to be investigated)
  • Migrate friendly-errors transformers/formatters to rspack system
  • Encore.disableRspack() method (for override if both bundlers are installed)
  • Automatic bundler detection if only one is installed (without explicit enableRspack() call)

Identified Risks

Risk Impact Mitigation
copy-files-loader.js uses internal webpack APIs 🔴 Blocking Mandatory rewrite (Phase 6.2)
Custom plugins incompatible with rspack hooks 🟡 Medium Manual testing, adapt if needed
Third-party loaders not compatible 🟡 Medium Document limitations, suggest alternatives
friendly-errors-webpack-plugin incompatible 🟢 Low Disabled, rspack has its own reporting

Resources

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions