Skip to content

[BUGFIX] rsbuild: handle plugin version - #773

Merged
Gladorme merged 1 commit into
perses:mainfrom
Gladorme:versioning-lock
Aug 28, 2026
Merged

[BUGFIX] rsbuild: handle plugin version#773
Gladorme merged 1 commit into
perses:mainfrom
Gladorme:versioning-lock

Conversation

@Gladorme

@Gladorme Gladorme commented Aug 19, 2026

Copy link
Copy Markdown
Member

Description

In spec of plugin we can define "metadata" (version + registry) and when I wanted to implement it on frontside, I got some issue when there is multiple instances of a same plugin with different versions.

Makes plugin builds version-aware so multiple versions of the same plugin can be installed and loaded side by side. Previously only the latest installed version of a plugin was actually loadable — any other version either failed to load or silently rendered the latest one's code.

1. Version in the asset prefix

getPublicPath now returns /plugins/<name>~<version>/ instead of /plugins/<name>/. The version is read from the plugin's package.json at build time.

Why: a manifest fetched from /plugins/<name>~<version>/mf-manifest.json resolved its (relative) remoteEntry against the version-less prefix. The server maps a path with no ~version to LatestVersion, so an older version requested the latest version's directory. Since chunk filenames are content-hashed, the file didn't exist there:

RUNTIME-008 ScriptNetworkError resourceUrl: /plugins/TimeSeriesChart/__mf/js/TimeSeriesChart.7c5da441.js (404)

This also explains why the newest version always appeared to work, and why an older version worked right up until a newer archive was dropped in.

2. Version in the Module Federation container global name

Sets library: { type: 'global', name: '<Name>_<version>' }, so the manifest's globalName is unique per version.

Why: MF resolves a remote's container via globalThis[globalName], taken from the manifest (assignRemoteInfo in @module-federation/runtime-core), and loadEntryScript early-returns an already-registered container:

  const { entryExports } = getRemoteEntryExports(name, globalName);
  if (entryExports) return entryExports;

With every version sharing the global name, the first version loaded won and later versions silently reused its container without ever fetching their own entry.

3. Version in the webpack chunk registry

Sets output.uniqueName and output.chunkLoadingGlobal to chunk_<Name>_<version>.

Why: async chunks register into a shared global array:

  (self.chunk_TimeSeriesChart = self.chunk_TimeSeriesChart || []).push([["53"], { 10985(...) }])

When two versions share that global, the second one pushes its chunks into the runtime the first installed, and because module IDs are deterministic they collide: both versions resolve to the first one's modules. chunkLoadingGlobal is set explicitly because rspack derives it from uniqueName before the tools.rspack hook runs, so setting uniqueName alone is not enough.

Plugins must be rebuilt for this to take effect; it is not retroactive for already-published archives
I did not handle registry name to have super long name, because I am not sure it will happen often 🙏
I guess if someone has the issue, he can change plugin name as quick win/fix

Checklist

  • Pull request has a descriptive title and context useful to a reviewer.
  • Pull request title follows the [<catalog_entry>] <commit message> naming convention using one of the
    following catalog_entry values: FEATURE, ENHANCEMENT, BUGFIX, BREAKINGCHANGE, DOC,IGNORE.
  • All commits have DCO signoffs.

UI Changes

  • Changes that impact the UI include screenshots and/or screencasts of the relevant changes.
  • Code follows the UI guidelines.

@Gladorme Gladorme changed the title [BUGFIX] rsbuild: Add plugin version in asset prefix [BUGFIX] rsbuild: handle plugin version Aug 19, 2026
Signed-off-by: Guillaume LADORME <Gladorme@users.noreply.github.com>
Comment thread rsbuild.shared.ts
if (process.env.NODE_ENV !== 'development') {
config.output.publicPath = 'auto';
}
// Isolate each version's webpack runtime.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this probably is not needed as we should use the path, regardless if the chunk has the same name

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure if I remove it, it will fail :/
I will check tomorrow

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I confirm without this unique identifier, there is issue (it's only using chunks from higher version). How to replicate in local: hardcode a color for series in timeserieschart panel (TimeSeriesChartPanel.tsx), update plugin version, build plugin (percli plugin build --plugin.path=./timeserieschart --skip.npm-install=true). Redo this a second time with another color and other plugin version.
Then check in panel editor preview when changing version in panel type selection, it will display the same color :/

Color example:

const seriesColor = `hsl(130 100% 50%)`;
const seriesColor = `hsl(276 100% 50%)`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok looking this in detail, I understand now this happens when two exact same versions run in parallel, for example in dev mode.

@ibakshay

Copy link
Copy Markdown
Contributor

Thank you for your work. It works great already. I just found a small bug when I was testing.
Both lock and unlock button shows up after you edit a panel by changing the description or query. And the version property in the panel gets removed when you apply the changes.

Screen.Recording.2026-08-22.at.21.58.22.mov

@Gladorme

Copy link
Copy Markdown
Member Author

Thank you for your work. It works great already. I just found a small bug when I was testing. Both lock and unlock button shows up after you edit a panel by changing the description or query. And the version property in the panel gets removed when you apply the changes.

Screen.Recording.2026-08-22.at.21.58.22.mov

Issues fixed: perses/spec#74 and for double buttons 😄

@Gladorme
Gladorme marked this pull request as ready for review August 27, 2026 07:56
@Gladorme
Gladorme requested a review from a team as a code owner August 27, 2026 07:56
@Gladorme
Gladorme requested review from jgbernalp and removed request for a team August 27, 2026 07:56
@jgbernalp

Copy link
Copy Markdown
Contributor

I'm checking from my side but other plugins different from prometheus still don't work. It seems the backend is not loading the latest version when no registry or version are provided. I'm testing...

@jgbernalp

Copy link
Copy Markdown
Contributor

I saw an issue with the backend version check, fixing it with: perses/perses#4387

I'm still checking from the frontend side...

@Gladorme
Gladorme added this pull request to the merge queue Aug 28, 2026
Merged via the queue into perses:main with commit 88e185b Aug 28, 2026
18 checks passed
@Gladorme
Gladorme deleted the versioning-lock branch August 28, 2026 10:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants