Skip to content

feat: add AI-agent assisted rspack addition - #2912

Draft
jackw wants to merge 24 commits into
jackw/agentic-additionsfrom
jackw/agentic-rspack-addition
Draft

jackw wants to merge 24 commits into
jackw/agentic-additionsfrom
jackw/agentic-rspack-addition

Conversation

@jackw

@jackw jackw commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

What this PR does / why we need it:

Adds rspack, the first hybrid addition built on the agentic additions in #2898. It moves a plugin's frontend build to rspack 2, from either webpack or the existing experimental rspack setup:

npx @grafana/create-plugin@latest add rspack            # asks before using an installed agent
npx @grafana/create-plugin@latest add rspack --no-agent  # codemod only, prints the instructions

There's quite a few that plugins extend the create-plugin webpack config with a root webpack.config.ts, and no codemod can port those reliably. So the work is split:

  • Codemod (scripts/rspack.ts): changes only what create-plugin owns (.config/, deps, scripts) and adds a root rspack.config.ts that fails the build until the custom config is ported.

  • Agent (prompts/rspack.md): ports the plugin's own config. It covers:

    • an API mapping and the known traps: lookups by loader or plugin name, native ESM loading, rspack 2 option moves, stacked transpilers, and images the new base config no longer copies;
    • commenting out anything unportable under TODO(rspack): so the build stays green;
    • install, typecheck, build and dev checks.

Here are a couple of demo videos:

rspack-agentic-codemod-basic.mp4
rspack-agentic-codemod-custom.mp4

Which issue(s) this PR fixes:

Relates to #2310. Supersedes #2526.

Special notes for your reviewer:

  • This is stacked on feat: add AI-agent assisted additions to create-plugin #2898 so we'll need to land that first. This PR's base is jackw/agentic-additions, so the diff shows only the rspack work.

  • This addition aims to replace the experimental Rspack feature flag with an officially supported Rspack build config.

  • Locally tested:

    • grafana-pyroscope-app: the codemod ran, the agent ported the 88-line root config, and typecheck, build and dev passed. The hardest part was a CopyWebpackPlugin filter function, which the agent replaced with globOptions.ignore.
    • vaduga-mapgl-panel (experimental rspack hand-pinned to 2.2.6): the codemod reset .config; the agent found nothing left to do. The build output was unchanged.
    • --no-agent, running from inside an agent session, and a second run on already-migrated plugins, which changed no files.
    • The interactive Claude Code session on a plugin of my own.

I've yet to test Codex and CDN-hosted plugins.

🤖 Generated with Claude Code

jackw added 21 commits October 1, 2026 08:00
Allow codemods to override template data without re-wiring
the full template rendering pipeline.
Import BannerPlugin, CopyRspackPlugin and SubresourceIntegrityPlugin as
named exports from @rspack/core. SubresourceIntegrityPlugin moved out of
rspack.experiments in rspack 2; the top-level export also exists in
rspack 1.7, so the template keeps working for current users.
Bump @rspack/core and @rspack/cli to ^2.2.0, add rspack-merge for
extending the config, and raise ts-checker-rspack-plugin to ^1.4.0, the
first release whose peer range includes @rspack/core 2.
Bring over changes made to the webpack template after the rspack one was
added: the exported Env type, the plugin id and version banner line, and
ReplaceInFile test patterns so nested plugin.json files get their
placeholders replaced. Also read the plugin id and version once.
eslint-webpack-plugin relies on compilation hooks rspack does not call,
so it never reported lint errors in rspack dev builds. eslint-rspack-plugin
reports them and keeps watch running by default. It removed failOnError,
which had no effect anyway because the plugin only runs in development.
Rspack 2 needs Node 22.12 or later. Use the latest 22 minor so type
stripping, enabled by default from 22.18, is always available and the
rspack CLI loads TypeScript configs natively.
Bring the addition over from the add-rspack branch unchanged apart from
the name. It is not registered yet. The bundler files test now checks
the rendered content instead of the change type, because Context keeps
'add' for files added earlier in the same run.
Render the package.json template for rspack and for webpack, and use the
difference as the dependencies to add and remove. The addition then
installs rspack 2 and eslint-rspack-plugin, removes eslint-webpack-plugin,
and follows future template version bumps without its own list.
Re-render the rspack and bundler templates on every run instead of
skipping when .config/rspack exists, so stale rspack folders and the
experimental rspack setup are replaced too. Delete only the files
create-plugin scaffolded into .config/webpack and report the rest, and
explain when there is no bundler configuration to migrate.
Removing copy-webpack-plugin or swc-loader while a root webpack config
still imports them breaks the port before it starts. Scan root level
webpack.* and rspack.* files for each webpack-only package, keep the
ones they reference, and list them for removal after the port.
…d and dev

Replacing build and dev wholesale dropped chained commands, extra flags
and sub scripts like build:compile. Swap the webpack command and config
arguments in place across all scripts, map each config path to its
rspack counterpart, and report scripts that still run webpack in a way
the addition cannot rewrite.
Detect any root webpack.config extension, never overwrite an existing
root rspack config (addFile threw on a second run), and write the stub
as an ESM safe rspack-merge config with a TODO(rspack) marker and an
error that explains how to finish the port.
Raise engines.node to >=22.23 when the plugin allows older Node versions
than rspack 2 and native TypeScript config loading need. When npm has
rspack 1 locked, drop the locked @rspack packages so the install can
resolve rspack 2 instead of failing with ERESOLVE. Also cover the
experimental rspack starting point in tests.
The codemod half moves create-plugin owned files to rspack 2. The prompt
covers the part that needs judgement: porting a root webpack config, or
upgrading an experimental rspack config, to rspack 2. It lists the API
mapping and known traps, and asks for unportable code to be commented
out with TODO(rspack) so the build still passes.
…them

The template scaffolds @swc/helpers for every plugin, but webpack builds
never needed it and many plugins removed it. The rspack base config runs
builtin:swc-loader with externalHelpers, so their builds failed to
resolve @swc/helpers. Add the packages the base config loads when they
are missing, and leave existing versions alone. Found by running the
addition on grafana-pyroscope-app.
…sions

Deriving the packages from the difference between the rspack and webpack
renders of the package.json template hid what the addition installs and
would do nothing once the experimental flag is removed. Name the packages
in three explicit lists and take only their versions from the template,
so they stay in step with the rendered .config files. Render the template
with fixed data instead of the plugin's, and add tests that fail when the
template and the lists drift apart.
Replace terser-webpack-plugin with rspack's built-in SWC minimizer, so
rspack plugins no longer need terser or its webpack peer for minifying.

- Add the create-plugin banner after minification, so it stays the first
  two lines of module.js in the same format. Pipelines read it.
- Merge the per-chunk license files SWC extracts into a single
  LICENSE.txt with LicenseRspackPlugin, keeping the fix for #2740.
- Drop console.log and console.info with pure_funcs, which matches the
  previous drop_console list.

The rspack addition installs the new plugin file and treats
terser-webpack-plugin as webpack-only.
A root config that adds esbuild-loader, babel-loader or ts-loader for
the plugin's own code stacks with the base swc rule, so every file is
transpiled twice and the build still passes. grafana-asserts-app has
done this since its webpack config was created. Ask the agent to fold
any extra settings into builtin:swc-loader, drop the duplicate rule,
and report it.
…ying

The rspack addition re-renders .config, so existing plugins pick up the
narrower copy patterns from #2369 for the first time. Code that builds
runtime URLs to files under img/ then 404s while the build still passes.
Ask the agent to import those files so rspack hashes them and resolves
the public path, to copy only the files that cannot be imported, and to
check for this even when the plugin has no custom config.
@jackw
jackw force-pushed the jackw/agentic-rspack-addition branch from 8102295 to 91a86e7 Compare October 1, 2026 06:02
jackw added 3 commits October 1, 2026 08:52
The live reload server had no error listener, so an EADDRINUSE on port
35729 crashed the whole rspack watch after its first build, for example
when another plugin's dev build or an orphaned watcher held the port.
Log one warning instead and retry on later rebuilds. ws re-emits the
http server's errors, so both servers need the listener.

Also connect the client with ws:// rather than http://, and rename the
plugin to LiveReloadRspackPlugin.ts to match the other rspack plugins.
The addition removes the old liveReloadPlugin.ts from experimental
setups.
Grafana plugins emit no HTML. The scaffolded Grafana image adds the
livereload script to Grafana's own index.html, so the processAssets step
that rewrote .html assets never ran. Remove it with the unused delay,
appendScriptTag and protocol options. This also clears the type errors
that code had.
The agent instructions told agents in rspack plugins that they must use
webpack, and the .config README only explained how to extend the webpack
config. The rspack addition's own agent reads those instructions first.
Render both files for the plugin's bundler, and have the addition
re-render them with the rest of .config.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 🧑‍💻 In development

Development

Successfully merging this pull request may close these issues.

1 participant