Skip to content

Vue3 migration organization #13622

Description

@GVodyanov

Related to nextcloud/groupware#64

Wave A — preparation, merged to main, shipped on Vue 2.7

Wave A ships as three PRs, one per section below. Each section is a single theme, is
independently releasable, and is independently revertible. The item IDs (A1A18) are stable and
still index the per-item detail in §3; only the packaging changed.

Merge order is A-1 → A-2 → A-3, because A-3 contains A11, which rewrites the import line of nearly
every component and will conflict with anything still in flight.

A-1 — Template API alignment (@nextcloud/vue prop, event and slot renames) #13589

Everything the v8.40 forward-compatible aliases already accept: props renamed, events renamed, slots
renamed, booleans inverted. Mechanical, template-only, no behaviour change on Vue 2.7. Land the items
in the listed order and rebase between them — they touch overlapping component files.

  • A4:checked / @update:checkedv-model / @update:model-value on NcCheckboxRadioSwitch, NcActionCheckbox, NcActionRadio (13 files)
  • A5:value / @update:value / @inputv-model / @update:model-value on the 13 other input components (32 files)
  • A6type="primary|secondary|…"variant=, and native-typetype on NcButton / NcActions / NcDialogButton

A7 #default#icon slot on NcInputField / NcTextField / NcPasswordField

A-2 — Retire the Vue-2-only dependencies and component APIs #13626

Everything that has to stop being a Vue-2-only package or a removed-in-v9 component API. Few files,
but the only hand-written UI in Wave A, so this is the section that needs manual testing. Give each
replacement its own commit and its own QA pass — see §8.

  • A2 — Drop the unused v-tooltip plugin from src/main.js (imported, registered, never used in a template)
  • A8isMobile mixin → useIsMobile() composable (src/components/MailboxThread.vue, the only user)
  • A10FilePickerVue component → getFilePickerBuilder() function (4 files)
  • A13 — Replace vue-autosize (Vue-2-only, no successor)
  • A14 — Replace @riophae/vue-treeselect in MailboxInlinePicker.vue (Vue-2-only, unmaintained) — revives #13412
  • A15 — Replace vue-tabs-component in AccountForm.vue (Vue-2-only) — revives #13411
  • A16 — Replace vue-dndrop in quickActions/Settings.vue (Vue-2-only) — revives #13413
  • A17 — Verify emojiSearch / emojiAddRecent import path for v9 (TextEditor.vue)

A-3 — Module boundaries and the v9 audit

Everything that changes how modules are imported rather than how components are used, plus the
written-down audit of what Wave B will have to repair. A11 is the whole reason this section is last.

The three are close in size for different reasons: A-1 is the most files but one changed line per
site; A-2 is the fewest files but the only real new code; A-3 is ~50 mechanical files plus a
document. If A-2's replacements turn out larger than estimated, split A14–A16 out rather than
letting the PR grow past a few thousand lines.

Wave B — the flip, stacked onto the vue3 branch

Nothing here works on Vue 2. Land these onto vue3, then merge vue3main once.

  • B1 — Dependency bump (#13407, rebase)
  • B2patch-package: fix or drop patches/splitpanes+2.4.1.patch (v9 ships splitpanes 4.x)
  • B3 — Entry points → createApp (#13405/#13408, pick one, rebase)
  • B4 — Router → createRouter / createWebHistory (folded into B3)
  • B5.syncv-model:prop (#13410, rebase — 13 sites, 10 files)
  • B6 — CKEditor → @ckeditor/ckeditor5-vue (#13414, rebase)
  • B7vue-shortkeyvue3-shortkey
  • B8 — Remove vue-frag (NavigationAccount.vue) — Vue 3 has native fragments
  • B9 — Remove .native modifiers (4 sites) and add the corresponding emits declarations
  • B10<template functional> → plain SFC (src/components/icons/JunkIcon.vue)
  • B11<transition> class renames: v-enterv-enter-from, v-leavev-leave-from (3 components)
  • B12 — Collapse the set/del shim from A3 into plain assignment (one-file diff)
  • B13 — Unit tests: @vue/test-utils v1 → v2 (#13415, rebase)
  • B14vitest.config.js: @vitejs/plugin-vue2@vitejs/plugin-vue
  • B15eslint.config.mjs: recommendedVue2recommended, then npm run lint:fix
  • B16 — Pinia 2 → 3, @pinia/testing bump, drop PiniaVuePlugin
  • B17 — Add explicit emits: declarations across components (ESLint vue/require-explicit-emits)
  • B18 — Drop the Nextcloud.js mixin in favour of app.config.globalProperties or per-file imports
  • B19 — CSS repair pass: box-sizing: border-box on modals/popovers, vs__* (vue-select 4), @vuepic/vue-datepicker replacing mx-datepicker
  • B20npm run build clean, npm run lint clean, npm run stylelint clean, npm run test:unit green
  • B21 — Replace Vue.set/Vue.delete with a local set/del shim (55 call sites, 3 files): refactor(store): replace Vue.set/Vue.delete with direct assignment #13392

Wave C — after the flip

  • C1 — Full manual QA pass against the §8 matrix
  • C2 — Playwright e2e suite green (npm run test:e2e)
  • C3 — Design review, then follow-up styling PRs (calendar did exactly this — do not block the merge on pixel polish)
  • C4 — File upstream bugs against @nextcloud/vue for anything broken in the library itself
  • C5 — Bump appinfo/info.xml if the Nextcloud minimum has to move
  • C6 — Optional follow-ups: Options API → Composition API, <script setup>, TypeScript

Activity

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

Metadata

Metadata

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions