Page MenuHomePhabricator

Determine whether the shared component library should support Vue 2 or Vue 3
Closed, ResolvedPublic

Description

Summary

Which Vue.js version should our shared component library target, and how can we plan/facilitate migration of projects from Vue 2 to Vue 3?

Considerations

Why does this matter?

This is closely tied up in the question of whether the library should continue supporting IE11 (T286947), because Vue 2 will continue supporting IE while Vue 3 will not. Many Vue 3 features (like the composition API) either already exist for Vue 2 or will be backported in an upcoming 2.x release. However, this is not true for many of the Vue 3 performance optimizations; if we want those we'll need to upgrade. Vue 3 also is fully written in Typescript and promises some improvements in TS workflow.

Impact on tooling
  • If we want to use more modern build tools like Vite (very fast, less config than Webpack, HMR), Vue 3 is supported natively while Vue 2 requires an additional plugin; using Vue 2 and continuing to support IE11 means we'll need to continue relying on things like Babel.
  • Different versions of the Vue.js browser DevTools are required to support Vue 2 vs Vue 3 apps, which is annoying. There may be other tools we're using that still rely mainly on Vue 2 – however, we're not really depending on any external Vue libraries so that is one less barrier to migration
Compatibility helpers
  • Vue 3.1 comes with an official "migration build" of the library (also called the "compatibility build" because the npm package is called @vue/compat), which provides backwards compatibility for almost all Vue 2 behavior. Almost all code written for Vue 2 (and all code written for Vue 3) should be able to run on this version of Vue.
  • Vue Demi could enable the component library to work in both Vue 2 and Vue 3 apps, but now that the official migration build of Vue is out, this might be obselete
Migration timeline
  • Do all WMF and WMDE applications *need* to migrate, or can some finished work remain in Vue 2 indefinitely?
  • Are we migrating projects to Vue 3 at the same time that we are migrating them to a shared component library, or are these separate processes?
  • Consider the collision of one product that's on Vue 2 and another that's on Vue 3: is this a big problem (avoid at all costs) or no big deal?
Relevant Links

Questions

1. When will the shared component library migrate to Vue 3?

Options:

  • Use Vue 3 in shared lib starting now
  • Use Vue 2 in shared lib indefinitely
  • Use Vue 2 in shared lib for now and re-evaluate in 6 months to 1 year (implies future migration work will need to be done both for library and for consuming applications)
  • Use the Vue compatibility build (or vue-demi) to attempt to write a shared library that can be consumed in both Vue 2 and Vue 3 applications

Design Systems Team proposal: To avoid additional migration work in the future, start developing the shared component library in Vue 3 immediately. Introduce this version of the library into MediaWiki once we update the version of Vue within MediaWiki to the migration build of Vue 3.1.
Fallback option: if some of us want to adopt the shared component library ASAP but must continue to support IE for a while, continue developing the library in Vue 2 with the composition API plugin, and plan for a future migration to Vue 3. This wouldn't prevent us from migrating other code to Vue 3: if MediaWiki upgrades to the migration build of Vue 3.1, embedding a library built with Vue 2 will continue to work.

2. When will existing WMF and WMDE Vue work migrate to Vue 3?
3. How will we enable and facilitate these migrations?

Design Systems Team proposal: Use the compatibility build to facilitate project migrations, and to support projects running Vue 2 or Vue 3 in the meantime. Eventually, upgrade the Vue version off the compatibility build. See T251974 for full details.

4. How will we handle situations where some projects use Vue 2 and some use Vue 3?

Design Systems Team proposal: Lean on the compatibility build to prevent collisions while we're in the middle of the migration process. This way there's only one version of Vue (the migration build of Vue 3.1) running on our pages, supporting both code written for Vue 2 and code written for Vue 3.
Alternative: Providing both Vue 2 and Vue 3 in MediaWiki is messy and suboptimal, but possible in principle. Vue 2 and Vue 3 can even coexist on the same page (see T251974#6862536). Supporting this while also allowing the component library to be used in both Vue 2 and Vue 3 would be possible in theory, if certain challenges with dependency management in ResourceLoader can be solved.


Decision

The new shared component library will be built in Vue 3. At some point soon, MediaWiki will also upgrade its bundled copy of Vue.js to the 3.2 compatibility build (which also ends IE11 support for all code that uses the library). The compatibility build of Vue defaults to Vue 2 behavor, and individual projects will be able to opt-in to Vue 3 behavior on an individual (or even component-by-component) basis.

See T286947 for more details about what this means for legacy browser support.

Event Timeline

Here's are some rough notes I took detailing some of the benefits of Vue 3:

New stuff
  • Composition API: allows for decoupling of logic, follows standard JS/TS patterns for extending and sharing code rather Vue-specific ones. More flexible code organization and logic reuse.
  • Teleport: a new component that allows you to move component code to a different part of the DOM outside the Vue app (e.g. <teleport to="body">
  • Fragments: support for multi-root node components (no longer need a single root element in the template)
  • emits component option: new thing in the Options API to define emitted events for that component for added documentation
  • Multiple (named) v-models: you can bind multiple v-models (with different names) to a single element (e.g. v-model:name="name" v-model:age="age"), used mostly for forms
  • Global mounting: no longer use global Vue instance to install plugins/libraries; use createApp from Vue. This protects the Vue app from third party libraries/plugins we use which might override or make changes to the global instance
  • Improved slots: compiler-generated slots are now functions and invoked during the child component's render call. This ensures that dependencies in slots are collected as dependencies for the child instead of the parent. so, when slot content changes, only the child re-renders. and when the parent re-renders, the child doesn't if its slot content didn't change
  • Experimental:
    • Composition API syntax sugar: <script setup>
    • Component-state-driven CSS vars: use v-bind(variableName) to use vars defined in component data in CSS within SFCs
    • Some improvements to scoped styles
    • <suspense>: component that can show a fallback component while waiting on an async request
Reactivity system
  • Vue 3's reactivity API has been completely overhauled. It now uses proxied objects for dependency tracking and change notification
  • Unlike in Vue 2, the reactivity API is exposed to the developer, giving you the ability to ensure everything is reactive
  • Things that weren't reactive in Vue 2 (e.g. adding/removing items from objects, which required vue.set and vue.delete respectively) are in Vue 3
  • See Vue docs for more details
Better TypeScript support
  • Composition API means that internal functions follow typical JS patterns, which allows for better TS support. Better type inferences with bindings returned from setup, along with props declarations used to infer types
  • Vue3's internals are written in TS
Other improvements
  • Faster: compile-time hints have been added to Vue3 features to reduce runtime overhead. Helps avoid unnecessary condition branches and re-renders. Up to 80% faster component instance initialization and half the memory usage
  • Smaller: Vue3 is smaller and tree shaking-friendly. Core runtime shrunk from 20kb to 10kb (gzipped)
  • Improved custom directives API
AnneT added a subscriber: Catrope.
egardner updated the task description. (Show Details)
egardner updated the task description. (Show Details)