Give ?vue3 SFC copies their own hot-reload record id
What does this MR do and why?
Fixes #629099: on the rspack dev server, super sidebar flyout menus do not open on pages with a Vue 3 migration flag enabled (for example /-/automate/agent-sessions with vue3_migrate_duo_agents_platform), and the console shows:
[Vue warn]: Error in render: "TypeError: Cannot read properties of undefined (reading '_base')"
found in ---> <GlModal> <FeatureLibraryModal> <SidebarMenu> ...
TypeError: Cannot read properties of undefined (reading 'componentInstance')Root cause
vue-loader15 computes the hot-reload record id ashash(shortFilePath), without the resource query, somodal.vueandmodal.vue?vue3share one id.vue-hot-reload-apiis deliberately a single shared module for both realms (SCANNER_BYPASS_PACKAGESinconfig/rspack/vue3_infection_loader.js), so both copies register into onemap.- The generated hot-reload code is
isRecorded(id) ? api.reload(id, options) : api.createRecord(id, options). On a clean page load, the second copy to execute callsapi.reload(), whoseupdateOptions()copies its options onto the first copy's options object. The Vue 2GlModalends up with a@vue/compatBModalconstructor incomponents. - A compat constructor has
superbut nosealedOptions, so Vue 2'sresolveModifiedOptionsthrows on the first options key,_base. The sidebar render aborts and the flyouts never mount.
Only development builds emit the hot-reload code, so production is unaffected. Vite is also unaffected: @vitejs/plugin-vue2 only calls createRecord on load and never reload, verified both on a clean load and on a hot update of a component loaded in both realms.
Fix
The vue-loader patch appends -vue3 to the hot-reload id when the resource query contains vue3, so each realm keeps its own record. The scoped CSS id is not touched.
Verified on a Caproni rig running rspack: before the change window.__VUE_HOT_MAP__ held one GlModal record whose Ctor.super.version was 2.7.16 while options.components.BModal.super.version was 3.5.42 (seven @gitlab/ui components were mixed this way: GlModal, GlTooltip, GlPopover, GlTable, GlDropdown, GlTabs, GlDropdownForm). After the change there are separate 932f7b4a and 932f7b4a-vue3 records with the right Vue version each, the console is clean and the Manage flyout opens.
How to set up and validate locally
- Use the rspack dev server (GDK default) and clear its cache once so the patched loader output is used:
rm -rf tmp/cache/rspack. Feature.enable(:vue3_migrate_duo_agents_platform).- Open a project's
/-/automate/agent-sessionspage and hover a collapsed sidebar section such as Manage. - Without this MR:
_baseerror in the console, no flyout. With this MR: no errors, flyout opens.
MR acceptance checklist
- I have evaluated the MR acceptance checklist for this MR.