Draft: [POC] Remove Vue 2
What does this MR do and why?
Proof of concept. Do not merge.
This MR builds GitLab with no Vue 2 at all. It answers one question: what breaks when Vue 2 is gone? #634491 tracks the real removal.
The full pipeline passes, including E2E on Omnibus and CNG and the as-if-FOSS pipeline: https://gitlab.com/gitlab-org/gitlab/-/pipelines/2972081727. It ran on the stack rebased on 2026-10-21.
The MR is stacked on !263251 (merged), which compiles templates with the Vue 3 compiler in the Vue 3 CI jobs. That MR is itself stacked on the spec fixes in !263821 (merged). Most fixes for the Vue 3 compiler are already in those MRs or on master.
The commits on top of it form the task list for the real removal. Some tasks work while Vue 2 is still installed, so they can merge first, as separate MRs. The others only make sense once Vue 2 is gone.
Tasks that can be done before Vue 2 is removed
Each of these works with Vue 2 and Vue 3 side by side.
- Update
@gitlab/uito 138.7.0, with therouter-linkfixes inGlNavItemandGlLink. Merged in !263855 (merged). - Find an empty catalog input description in QA when it is hidden. Merged in !263634 (merged).
- Register
DisabledByPolicyPopoverandPolicyBadgein the CEbranch_rule.vue. The Vue 3 compiler resolves every component in a template, even one behind a falsev-if. Merged in !263806 (merged). - Build Storybook with Vue 3. !263808 (merged) does this. Storybook has its own
package.json, so it can switch before the app does:- Use
@storybook/vue3-webpack5andvue-loader17. - Give the preset's loader the GitLab compiler options.
- Drop the preset's
vue$alias, so stories use@vue/compatlike the app. - Bind the story args in the global decorator, because the Vue 3 renderer passes no props to a story.
- Use
- Move
chalktodependencies.scripts/frontend/postinstall.jsneeds it, and production installs get it only throughvue-loader15. - Read templates with the Vue 3 compiler in the gettext extractor. The plain compiler crashes on
notes/components/diff_with_note.vue, so the extractor uses the compiler wrapper and compat options of the bundler. - Finish the rollout: mark every
vue3_migration.ymlentry asmigrated. The 373 entries withstatus: rolloutthen build once, under their own name. - After the rollout, delete the 100 unused
vue3_migrate_*feature flags, and expect no rollout entries in the Vue 3 migration spec. - Remove the Omnibus
vue3-rolloutE2E job andqa/.../vue3_rollout_spec.rb. The job enablesvue3_migrate_jobs, and that flag goes with the step above. Not done in this POC yet.
Tasks that must be done when or after Vue 2 is removed
- Build and test with Vue 3 by default.
VUE_VERSIONandVUE_COMPILER_VERSIONdefault to3in webpack, rspack, Vite and Jest. Vite no longer imports the Vue 2 plugin or compiler. - Remove Vue 2 and its packages:
vuechanges to3.5.43vue-template-compilervue-loader15@vitejs/plugin-vue2@vue/vue2-jest- the Vue 2 versions of
vuex,vue-router,vue-apollo,portal-vueandvue-virtual-scroll-list
- Add Vue Test Utils 2 under its own package name, and let the Jest Vue mock re-export the aliased
vue. - Keep the aliased packages external in the ESLint
import-x/orderrule. The resolver mapsvue,vuexand the others to files in the repo, so apathGroupsentry is needed. - Drop the
-vue3suffix from the assets image tag inscripts/utils.sh. The suffix kept the Vue 2 and Vue 3 images apart. With Vue 3 as the default, Omnibus waited for an image that was never pushed. - Remove the duplicate
vue3CI jobs, such ascompile-production-assets vue3. They now build exactly what the default jobs build. Not done in this POC yet. - Remove the migration code:
config/vue3migration/, the infection scanner,lib/gitlab/vue3_migration.rband the?vue3imports. Not done in this POC. - Replace the Vue 2 libraries that still work through the aliases. Not done in this POC:
@tiptap/vue-2@testing-library/vue5vuedraggable2vue-resizeandvue-observe-visibility, which the vendoredvue-virtual-scrollerimportsportal-vue2, a dependency of@gitlab/uiand@gitlab/duo-ui
- Fix the
Failed to resolve component: router-linkwarning fromGlNavItemin the super sidebar. See the screenshots section.
Labels
pipeline:run-all-e2e runs the full E2E suite against the Omnibus and CNG packages. pipeline::tier-3 runs the full pipeline.
Screenshots or screen recordings
Checked in GDK with the rspack dev server, which logged Using Vue.js 3 (compiler 3) and built with no errors. Signed in as root:
| Page | Apps mounted under Vue 3 | Console errors |
|---|---|---|
| Project jobs list | top bar, sidebar, breadcrumbs, JobsTableAppRoot |
none from Vue |
| Merge request changes tab | 20 apps, including the MR header, sidebar widgets and file browser | none from Vue |
| Work item | WorkItemsRoot, DuoPanel. The rich text comment editor (tiptap) accepts input, and **text** turns bold. |
none |
| Pipeline | PipelineHeaderApp, PipelineDetailsRoot. The graph shows 100 jobs. |
none |
The only error on these pages is a 401 from the performance bar, which is not related to Vue.
One development warning repeats on every page: Failed to resolve component: router-link, from GlNavItem in the super sidebar. The Vue 3 compiler resolves router-link before it picks the v-if branch, and these pages install no router. The links render as plain <a> elements. It is a cleanup item, not a breakage.
How to set up and validate locally
- Check out this branch and run
yarn install. - Restart the GDK frontend server and Rails.
- Open a project's jobs page.
- In the browser console, run
document.querySelector('[data-gitlab-vue3-app]'). It returns the root element of the jobs app, which mounted under Vue 3.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
References
- Plan to remove Vue 2: #634491
- Parent epic: &6252
- Stacked on: !263251 (merged)
@gitlab/uiupdate: !263855 (merged)- CE branch rule fix: !263806 (merged)
- Spec fixes under the stack: !263821 (merged)
- Storybook on Vue 3 MR: !263808 (merged)
- QA catalog fix: !263634 (merged)
- Global bundles and
main: #623999 - Storybook on Vue 3: #555929
- Passing pipeline: https://gitlab.com/gitlab-org/gitlab/-/pipelines/2972081727
- Passing pipeline before the 2026-10-21 rebase: https://gitlab.com/gitlab-org/gitlab/-/pipelines/2970449945