Migrate from webpack to Rspack
This guide explains how to move the frontend build of your plugin from webpack to Rspack 2 with the rspack addition of the create-plugin tool. It also applies to plugins that use the experimental Rspack setup from earlier versions of create-plugin.
Before you begin​
- Commit or stash your changes. The
addcommand stops if the repository has uncommitted changes. - Use Node.js 22.23 or later. The migration raises
engines.nodein yourpackage.jsonfile to>=22.23if it allows an older version.
Run the migration​
From the root of your plugin, run the rspack addition:
- npm
- Yarn
- pnpm
npx @grafana/create-plugin@latest add rspack
yarn dlx @grafana/create-plugin@latest add rspack
pnpm dlx @grafana/create-plugin@latest add rspack
If you have Claude Code or OpenAI Codex installed, create-plugin asks whether to use it. The agent ports any custom build configuration in your project root to rspack.config.ts. When it finishes, create-plugin runs your typecheck and build scripts and lists anything the agent marked with a TODO(rspack): comment. Review the changes with git diff before you commit them.
To learn how agents work with the add command, refer to Add features to your plugin. If you don't have an agent, or prefer to port the configuration yourself, refer to Migrate without an agent.
What changes in your project​
The migration changes these files:
.config/rspack/: adds the Rspack base configuration..config/webpack/: removes the files thatcreate-pluginadded. The migration keeps any files of your own in this folder and lists them in the command output..config/bundler/: updates the helpers that the base configuration uses.package.json:- Adds the Rspack packages and removes the packages that only the webpack base configuration used. A package stays if a
webpack.*orrspack.*file in the project root still imports it. Thewebpackpackage always stays, because loaders in the Rspack base configuration depend on it. - Replaces
webpackwithrspackin your scripts. The command output lists any script it can't rewrite. - Raises
engines.nodeto>=22.23, if it allows an older version.
- Adds the Rspack packages and removes the packages that only the webpack base configuration used. A package stays if a
.config/.cprc.json: sets theuseRspackfeature flag, so that latercreate-plugin updateruns treat your plugin as an Rspack plugin.
If your plugin uses the experimental Rspack setup, the migration replaces the files in .config/rspack/ with the Rspack 2 base configuration and upgrades the Rspack packages. If you run create-plugin update before the migration, it only renames the useExperimentalRspack feature flag to useRspack.
Migrate without an agent​
To make the changes without an agent, run the addition with the --no-agent flag:
- npm
- Yarn
- pnpm
npx @grafana/create-plugin@latest add rspack --no-agent
yarn dlx @grafana/create-plugin@latest add rspack --no-agent
pnpm dlx @grafana/create-plugin@latest add rspack --no-agent
The command makes the changes listed in What changes in your project, then prints the path to an instructions file. If your plugin has no webpack.config.* or rspack.config.* file in the project root, the migration is complete. Otherwise, update that file as described in the following sections.
Port a webpack configuration​
If your plugin has a webpack.config.* file in the project root, the migration adds an rspack.config.ts file that stops the build with an error like this:
[rspack] webpack.config.ts has not been ported to rspack.config.ts yet.
The error prevents you from releasing a build without your customizations. To port your configuration:
-
Merge your customizations into the base configuration in
rspack.config.tswithrspack-merge:rspack.config.tsimport type { Configuration } from '@rspack/core';import { merge } from 'rspack-merge';import grafanaConfig, { type Env } from './.config/rspack/rspack.config.ts';const config = async (env: Env): Promise<Configuration> => {const baseConfig = await grafanaConfig(env);return merge(baseConfig, {// your customizations});};export default config; -
Replace webpack plugins and loaders with their Rspack equivalents. For example, replace
copy-webpack-pluginwithCopyRspackPluginfrom@rspack/core. For the full list, refer to Migrate from webpack in the Rspack documentation. -
Make the file work as a native ECMAScript module (ESM), because the Rspack CLI loads it that way. Replace
__dirnamewithimport.meta.dirnameandrequire()withimport, and add the.tsextension to relative imports. -
Comment out any code that has no Rspack equivalent, and add a
TODO(rspack):comment that explains what the code did. -
Remove the
[rspack]error. -
Delete the
webpack.config.*file and any files that only it imports.
The instructions file that the command prints covers more cases than this guide, such as configurations that look up base rules by loader name.
Upgrade an experimental Rspack configuration​
The migration doesn't change the rspack.config.ts file in your project root. Update that file for the changes listed in Migrate from Rspack 1.x, and replace webpack-merge with rspack-merge.
Check the result​
Run your checks and start the development build:
- npm
- Yarn
- pnpm
npm run typecheck
npm run build
npm run dev
yarn typecheck
yarn build
yarn dev
pnpm run typecheck
pnpm run build
pnpm run dev
After the build, check that dist/ contains module.js, plugin.json, and any file that your plugin refers to by path at runtime.
Troubleshooting​
The build fails with an [rspack] error​
The build configuration in your project root isn't ported yet. Refer to Port a webpack configuration.
ReferenceError: __dirname is not defined​
rspack.config.ts, or a file it imports, uses a CommonJS global. Replace __dirname with import.meta.dirname.
The build fails because an export doesn't exist​
Rspack 2 stops the build when code imports a name that a module doesn't export. In webpack, this was a warning. Fix the import in your code.
A file returns 404 at runtime​
Base configurations from older versions of create-plugin copied images, SVG and HTML files, and the img/, libs/ and static/ folders, into dist/. The current base configuration copies only plugin.json and other JSON files, the README, CHANGELOG and LICENSE files, query_help.md, and the logos and screenshots that plugin.json lists. If you created your plugin with an older version, the migration brings in this change.
If your code builds a URL to any other file, import the file and use the imported URL instead:
import howItWorks from '../img/how-it-works.svg';
export const HowItWorks = () => <img src={howItWorks} alt="How it works" />;
If your code builds the path at runtime, add a CopyRspackPlugin to rspack.config.ts for those files.
Next steps​
- To extend the Rspack configuration later, follow the steps in the
.config/README.mdfile of your plugin. - To learn more about additions and the
addcommand, refer to Add features to your plugin.