Vue.js

Vue.js is the Wikimedia Foundation's official choice for adoption as the future JavaScript framework for use within MediaWiki. The usage of Vue.js within MediaWiki remains experimental, and it is not ready for widespread use. This page documents guidelines, best practices, and resources for using Vue within MediaWiki. This is not a general guide for using or developing with Vue.js; for that, see the general Vue.js documentation.

History
Discussions about adopting a modern JavaScript framework into MediaWiki began in early 2019. In December 2019, an RFC on the subject was started. Vue.js was added to core MediaWiki in February 2020. The NearbyPages extension, the first MediaWiki extension to use Vue.js, was released soon afterwards. The RFC ended in March 2020, with the official decision to use Vue.js (though this decision was not clearly announced until August 2021). WVUI (Wikimedia Vue User Interface), the first attempt at a shared library for Vue.js-based components for use within Wikimedia projects, was created in May 2020. The first MediaWiki version to include Vue.js, and the related Vuex library, was 1.35, released in September 2020. A replacement library for Vue.js within Wikimedia, Codex, was started in September 2021 following feedback from WMDE, and WVUI became deprecated. Vue.js within MediaWiki was upgraded from version 2 to 3 in December 2021.

Vue within MediaWiki
Vue is bundled with MediaWiki as a ResourceLoader module. See below for details. MediaWiki currently includes the compatibility build of Vue.js v3.2, which provides compatibility for Vue 2 code. We are still in the process of migrating pre-existing Vue 2 code to Vue 3, and have upgraded from Vuex 3 to Vuex 4. New code should be written for Vue 3, and must set a compatConfig setting. See T289017 for more details on the migration plan.

Single-file components (.vue files) are supported via ResourceLoader. See Using Vue in MediaWiki for more information.

Server-side rendering of Vue components is not currently possible but is on the Wikimedia Foundation Design System Team's roadmap.

See the Design System Team's page or Phabricator workboard for more information about current work and future changes to Vue-related infrastructure.

State management
As mentioned above, Vuex 4 is available for use in MediaWiki. Pinia, the new official state management library for use with Vue 3 and successor to Vuex 4, is currently awaiting security review (see T308495). If you're building a project with Vue 3 and want to use Pinia, please add a comment to that task so we can connect the security review with a project timeline.

Codex Vue.js UI toolkit and component library
A new library containing Vue 3 components, design tokens, icons, and documentation is under development and will soon become available for projects within (and beyond) MediaWiki. The library, Codex, is managed by the Design Systems Team and built by collaborators across the community (including the Wikimedia Foundation, Wikimedia Deutschland, and volunteers). An initial release is planned for mid 2022 and will replicate the components and functionality offered by the legacy Wikimedia Foundation Vue component library, Wikimedia Vue UI (WVUI), which is now deprecated and in maintenance mode.

To learn more about Codex, check out:


 * Phabricator workboard (see the Design Systems Team workboard for sorted and prioritized tasks)
 * Code (or GitHub mirror)
 * Live demo site

Single-file components
Vue components in MediaWiki should use single-file components ( files), which combine the template, JavaScript and CSS for a component in one file. ResourceLoader understands these files natively: you can simply add them to your module as you would a regular  file, and you can   them in other files. The  block in each   file must export a component definition (an object with keys like ,  ,  , etc.) using. Styles can either be plain CSS (using ) or LESS (using  ).

A simple example of a single-file component looks like this:

Limitations
MediaWiki's support for single-file components is incomplete, and has the following limitations:


 * is not supported
 * Advanced style features, such as,  , and   in styles are not supported
 * Src Imports are not supported (but support for this feature could potentially be added, if developers find it useful)
 * Pre-processors, such as  or   (TypeScript) are not supported. For styles, only   is supported.
 * LESS styles are processed using MediaWiki's LESS processor, which uses an old version of LESS. On the other hand, this means all the features supported in other LESS files in MediaWiki are supported here too.
 * ES6  and   are not supported. Instead of , use  ; instead of   use  . Other ES6 syntax is supported.
 * ES2016 and newer syntax is not supported. Notable examples of unsupported syntax include the spread operator in object literals, / , and  /.
 * Self-closing tags for components (e.g. ) are not supported. Instead, you have to use open and close tags (e.g.  ).
 * Component tags using PascalCase (e.g. ) are not supported. Instead, you have to use kebab-case for component names (e.g.  ).
 * files are only supported in package modules (modules that use )

If you try to use an unsupported SFC feature, ResourceLoader will throw an error at runtime. Unsupported JS or template syntax results in a lint error, so make sure you set up linting for your code to catch these, as well as other pitfalls and style guideline violations.

Using components in other components
To use a component in another component,  it and add it to the   property of your component definition. We prefer using local registration, and avoid using global registration.

Mounting and initialization code
To mount your component to the DOM, use. This function works the same as, but adds shared MediaWiki-specific plugins for internationalization and error logging. The code mounting your component should be in a simple init file that requires the top-level component (plus any stores and plugins) and mounts it to a placeholder div. Other logic and UI code should live in other files (for example, the top-level component) as much as possible. Conventionally, the top-level component file is called, unless there are multiple entry points that each have their own top-level component.

A simple example of an init file would look like this: A more complex init file that uses a Vuex store and a custom plugin would look like this:

Module definition example
A simple example of a ResourceLoader module definition that pulls together all the examples above would look like this: Note that you must specify  as a dependency, because the code uses.

Note The Vue and Vuex versions loaded through ResourceLoader with the  array in   are not the same as the ones declared in. It's recommended to set the same versions in  that ResourceLoader will load. To see which version of each dependency will ResourceLoader use, consult the latest foreign-resources.yaml file from mediawiki/core.

Writing code for Vue 3
MediaWiki uses the compatibility build of Vue 3. This means that Vue will try to provide compatibility with Vue 2 code by default, which breaks certain Vue 3 features (in particular  on components, and setting attributes to  ). To avoid this breakage, all new code written for Vue 3 (and old code that has been fully migrated to Vue 3) must set  in the component definition of every component. For an example of how to do this, see the code sample above. Once all old code written for Vue 2 has been migrated to Vue 3, MediaWiki will migrate to the non-compatibility build of Vue 3. Once that has happened, these compatConfig settings will no longer be necessary.

Build step alternative
If you need functionality that is not supported by MediaWiki's Vue support or by ResourceLoader (e.g. TypeScript or tree shaking), you can use a build step that pre-compiles Vue templates and does tree shaking and minification. However, this requires additional per-repo configuration changes which are currently undocumented. This extra configuration will be eliminated or formalized and minimized if the deploy build step RFC succeeds.

Code style guidelines
See MediaWiki's Vue coding conventions, which are largely based on the official Vue Style Guide. We use ESLint to enforce these conventions; see here for how to set up ESLint in your repository.

General guidelines

 * Avoid globals of all kinds. Instead, pass the dependencies needed in from the outermost to the part that needs it.
 * Avoid jQuery as a dependency. There are several reasons for limiting jQuery usage including:
 * jQuery is a large dependency both in terms of bytes shipped to users (performance) and comprehension (API) but its usefulness is less and less. For libraries, jQuery as a dependency especially limits reusability by third parties.
 * The jQuery API is invasive--any usage returns jQuery specific types that are cumbersome to pick apart and usually results in further usage whether it’s truly necessary or not.
 * Usage of jQuery has encouraged construction of entire user interfaces by manually assembling bits and pieces of HTML wrapped in jQuery parser calls. This imperative style is challenging to read, verbose, difficult to maintain, unwieldy to compose, and doesn’t scale well to application development. For user interface development especially, Vue.js is the greatly preferred alternative.
 * Since the need for jQuery is diminishing, it is perceived as a redundant technology (e.g., GitHub removed its usage in 2018 and close proximity to or, worse, dependency on it makes our code appear out of fashion which is unbecoming to newcomers.

The i18n plugin
The  module comes with a small i18n plugin that wraps MediaWiki's i18n system, so you can use MediaWiki i18n messages in your templates. This plugin creates an  function that you can use inside templates, which is an alias for. For plain text messages (most cases), you can simply use: You can pass parameters either variadically, or as an array: The  function returns a Message object, so you can use it in all the same ways that you can use   in "normal" JS code. Remember that all message keys you use have to be added to the  array in the ResourceLoader module definition.

Parsed messages
Because parsed messages return HTML rather than text, they have to be invoked differently: Note that  doesn't work, because the   syntax only works for text, not HTML. If you try to use a parsed message this way, the user will see the resulting HTML as plain text.

See the documentation comments in  for a more detailed explanation of.

Complex use cases
If the parameters to a message are complex, or if both the message name and its parameters are dynamic, it may be better to create a computed property for the message, as follows: Note the comment overriding the ESLint rule. This is needed because using  is discouraged except when necessary. For more information, see the coding conventions.

Testing
You should write tests! The current recommendation is to use Jest.

See the Vue.js testing guide for more information about how to test Vue components in a MediaWiki environment.

Error reporting
Client side errors can be monitored in Logstash. Dedicated documentation forthcoming in T248884.

TypeScript
(coming soon)

IE 11
As MediaWiki is using Vue 3, any features built with it will not work with IE11. See Compatibility/IE11 for more information.

Skin

 * New Searchbar for Desktop Improvements (part of WVUI)
 * Synthetic performance tests were also setup as part of this project that compare the lazy load time, query to render time, etc between legacy search and the Vue search implementation. The dashboard can be seen at https://grafana-rw.wikimedia.org/d/GivPpdsGk/vue-vs-legacy-search?orgId=1

Extension

 * Extension:MediaSearch
 * Uses Vuex
 * Has a fallback PHP implementation of the basic UI for a no-JS experience
 * Jest unit tests
 * Content Translation's new dashboard and section translation
 * This approach uses webpack based build and offers hot reloading and close integration with Vue dev tools
 * Extension:MachineVision
 * Uses Vuex
 * Extension:GlobalWatchlist
 * Extension:NearbyPages
 * Extension:WikiLambda
 * MediaWiki Vue.js Sandbox (test extension)

WMDE/Wikibase

 * "microfrontends" "termbox" (currently on mobile only)
 * Wikidata Bridge (currently on selected Wikipedias only), see code
 * Tainted References

Miscellaneous

 * Codex UI toolkit (see live demo)
 * WMDE
 * Simple Query Builder (An easier way than SPARQL of querying Wikidata), see code
 * Wikit (Design System and Component Library), see code
 * Wikibase Vue.js components repo
 * The Toolhub catalogue

Most important

 * Official guide
 * Official API documentation
 * Official style guide
 * Official devtools browser extensions

Additional

 * Vue.js News (weekly newsletter)
 * Mozilla Developer Network (MDN) Vue.js documentation

Training vendors

 * Vue School
 * Frontend Masters
 * Vue Mastery (includes some free courses too)

From around MediaWiki

 * Successful Technical RFC on evaluating front-end frameworks within the MediaWiki ecosystem
 * 2020: The Year in Vue from the Wikimedia Tech Blog

GitLab

 * Vue.js frontend development guidelines
 * Why we chose Vue.js
 * How we do Vue: one year later