Proposed migration plan as of July 23, 2021 (some of the comments below may be contradictory and confusing, because I was working my way to this and hit some dead ends):
Based on all that, I think our migration plan could look something like:
- Write a wrapper for mounting components that mocks something like the Vue 3 API for Vue 2, and that mounts the component as a child of the given element, rather than replacing the element (i.e. the Vue 3 behavior rather than the Vue 2 behavior). For a draft of this wrapper, see here.
- Make all MW code that mounts components use this wrapper.
- Upgrade the version of Vue that is bundled with MediaWiki (and exposed as the vue ResourceLoader module) from version 2.6 of vue to version 3.2(*) of @vue/compat (once it's out), configured for Vue 2 mode. At the same time, change the wrapper to use the Vue 3 createApp API, and monkey-patch new Vue() and new Vue().$mount() to behave like Vue 2 rather than Vue 3 (for some reason, the Vue 3 compat build doesn't provide compatibility here). For a draft of what the wrapper would look like at this point, see here.
- Check that everything still works, and make minimal changes to fix things where necessary. There will be a million migration warnings, but that's OK.
- Change all code that uses Vuex to use the createMwApp() wrapper. This is necessary because Vuex 4 doesn't support new Vue( { store: store, ... } ), not even when using the Vue 3 compat build, and there seems to be no way for us to monkey patch that compatibility in either.
- Upgrade Vuex from 3.1.3 to 4.0.2 (or whatever the latest version is by then). Make the createMwApp() wrapper backwards compatible, so that createMwApp( { ..., store: store } ) still works. (Vuex 4 instead requires createMwApp( { ... } ).use( store ).) For a draft of this wrapper code, see here.
- Migrate things one by one, addressing their migration warnings until there aren't any left. This means migrating individual apps, whether they're using a build step or not, and the component library. These can be migrated piecemeal in any order.
- Once a component is migrated, it should set componentConfig: { MODE: 3 } in its component options. This ensures that compat features that get in the way of migrated code (such as ATTR_FALSE_VALUE) are disabled, and helps test that the component will work correctly in Vue 3.
- The component library can be migrated to Vue 3 directly (using the compat build as an aid, but without ever shipping a release of the library that uses Vue 3-compat), or built in Vue 3 from the ground up. Either way, it will need to set compatConfig: { MODE: 3 } on every component to make things work in MediaWiki as long as MW still uses the compat build. This could be done in the library or in MW's wrappers for the library.
- Once everything is migrated, try setting the global compatConfig to { MODE: 3 }, to test that everything really is migrated.
- Remove the global Vue.use( i18n ) calls, and change the i18n plugin to use the Vue 3 API (doing this earlier would make the i18n plugin unavailable to code using the Vue 2 mounting API).
- Switch the Vue build in MediaWiki from @vue/compat to vue. We're now running real Vue 3, without any compat behavior.
- At our leisure, remove compatConfig from everything.
(*) Version 3.2 is needed because it fixes a bug that breaks the i18n plugin
