Page MenuHomePhabricator

Research spike: vue.js and visual editor
Closed, ResolvedPublicSpike

Description

Research spike to explore the technical details of the Vue,js framework as it relates to the current architecture of VE. The outcome is to identify opportunities, risks, and areas for further exploration.

Milestones (Updated September 18, 2020):

  • Due September 21: Completed experiment wrapping top-level VE editor-component into a Vue component; document trade-offs and level of effort involved
  • Due October 1: Completed experiment creating a single component Vue interface wrap; document challenges, trade-offs, and level of effort involved
  • Due October 10: Draft migration plan circulated to team for feedback
  • Due October 20: Final migration plan completed

Research Questions:

  • What “things” (features, classes, patterns etc) are there to migrate?
  • Which of them will be challenging?
  • What patterns exist in vue.js which might fit with our existing codebase?
  • Is there any benefit to migrating our class and mixins handling to vue, now or in the future?
  • To vue components entirely?
  • To ES6 classes with a transpile step?
  • Are there any blockers in the coordination of sync and sync events to making VE a reusable vue component
  • Is anything in vue.js behaviors fundamentally inimical to, e.g., IME usage / contenteditable quirks?
  • For a complete port
  • For switching just the UI components in VE to vue
  • For a wrapper around VE which lets it be a contained vue component

Migration approaches

This document outlines the outcomes of the Editing Team's research and possible approaches for migrating the visual editor to vue.js. (limited access for now): https://docs.google.com/document/d/1bLlafj66X27CPKHiNt5QRcrNfARFduU7xleetUTXwTE/edit

Event Timeline

Restricted Application changed the subtype of this task from "Task" to "Spike". · View Herald TranscriptMar 6 2020, 11:56 PM

Due August 15: Draft migration plan circulated to team for feedback

I'm unsure if it's applicable but we're trying to build on the lessons learned from OOUI whenever building new Vue.js components. If it's useful, please consider contributing to this more general OOUI migration guide draft with your insights and corrections. Mistakes are my own but I've been trying to identify the typical procedure developers should follow when building a new component that has an OOUI counterpart. It's meant to be a practical approach and my thinking is that the more OOUI experts can help guide the migration, the less work they'll have to do themselves.

Due June 30: Completed experiment wrapping top-level VE editor-component into a Vue component; document trade-offs and level of effort involved

Top-level wrapper component seems practical, following general Vue external-library techniques. I.e. include all the external stuff separately, and just create a wrapper to anchor it to your Vue component tree via mounted/beforeDestroy hooks.

Model binding seems like a poor fit for VE's behavior. With just VE core and having HTML as the data, it's not awful, though it still causes selection issues due to replacing the document. VE-MW has an entire async API wikitext transform required in-between, though, which gets awkward.

It seems not unreasonable to just expose some getter/setter methods on such a component, and anything using it can accept that it's not a perfect vue data-exposing component.

Here's an example of such an implementation, which will put VE core onto a page while relying on all sorts of globals: https://github.com/kemayo/vue-visualeditor-example/blob/master/src/components/VisualEditor.vue

(This is the approximate level of VE implementation we have on our minimal demo.)

Further detail (from discussing with @DLynch): it's not clear what document data a top-level wrapper could usefully expose as a Vue-style reactive property.

  • As DLynch indicated above, we cannot obtain wikitext without making an async API wikitext transform HTTP request, which is a big enough deal that the caller should see explicitly when it happens, how to handle failure etc.
  • Ditto HTML.
  • We could expose the VE data model, but we couldn't make it writeable except in the sense of blowing the entire document away (unless we transformed splices on the data model into VE transactions, but these will get pushed onto the history and can fail, so again it's a big enough deal that the caller should see this explicitly) — and even for read-only usage, we couldn't readily emulate the normal Vue behaviour that view changes don't propagate to the model synchronously.

It seems in all these cases, it is in fact less confusing for the caller to call a function explicitly: that function can then return a promise or throw an exception as appropriate, and there's no false impression that data is being exposed according to the normal Vue conventions.

@DLynch + @dchan, before I mark this task as resolved, can y'all please add links to the artifacts you created as part of this research in the task description?

I'm coming late to this task, but I think that @santhosh's wrapper component is a good example of how to integrate a stand-alone 3rd party widget like VE into a Vue application as simply as possible (still relying on the underlying VE behavior, etc).

If you wanted a deeper integration where the text being edited existed in the reactive data of your component, but still needed to parse Wikitext, you might want to look into watchers. From the docs page: "This is most useful when you want to perform asynchronous or expensive operations in response to changing data" – a (debounced) watcher function could listen for changes in the source text and then hit the parsoid service to get new HTML output while the user types.

@DLynch + @dchan, before I mark this task as resolved, can y'all please add links to the artifacts you created as part of this research in the task description?

I've added the artifact (Vue and VE integration research) to the task description. Marking this as resolved as a result.