Wiki 3.0 Implementation choices - UI Framework

Hello all,

As we are starting prototyping for Wiki 3.0, we are also testing and benchmarking frameworks and libraries that we would potentially use for its development.

One important choice we have to face is the choice of the UI framework we will be using for building the interface.

We have several requirements for this matter, the first one being that the framework should be well-maintained, so that we can envision our project in the long term.
The framework should also have a great ecosystem (libraries / devtools / community forums & resources), so that there already are existing solutions and help for common problems we’ll have to solve.
Performance and scalability are also important requirements we want to satisfy.

There are 3 great frameworks that meet these requirements, being React, Angular and Vue.

For now, our choice stopped on Vue, for the following reasons:

  • we already have some positive experience with it, from the Livedata Macro
  • Vue has a very low learning curve, allowing people to easily get started with it
  • Vue allows great flexibility through its syntax, which is important for the type of software we want to build
  • even though Vue supports JSX, it also provides its own Single-File Components syntax, that allows to intuitively compose HTML, JS and CSS, without the need of additional frameworks

About using Web Components

Ideally we prefer standards, and therefore the Web components standards is very interesting.

Now as stated on the Vue page on web components, web components do not provide all the features that a framework like Vue provides

There is indeed a certain level of feature overlap between Custom Elements and Vue Components: they both allow us to define reusable components with data passing, event emitting, and lifecycle management. However, Web Components APIs are relatively low-level and bare-bones. To build an actual application, we need quite a few additional capabilities which the platform does not cover:

  • A declarative and efficient templating system;
  • A reactive state management system that facilitates cross-component logic extraction and reuse;
  • A performant way to render the components on the server and hydrate them on the client (SSR), which is important for SEO and Web Vitals metrics such as LCP. Native custom elements SSR typically involves simulating the DOM in Node.js and then serializing the mutated DOM, while Vue SSR compiles into string concatenation whenever possible, which is much more efficient.

Vue’s component model is designed with these needs in mind as a coherent system.

However, as Vue is compatible with Web Components, one approach would be to use Vue to generate Web Components as the basis components for the wiki 3.0 design system, thus getting more framework independent.

We would be interested to have your feedback on this subject, discussing what UI framework to use for the Wiki 3.0, and how the project would benefit from this choice.

Thanks,
Clément

I’m +1 using Vue, provided we are being careful about certain aspects:

1/ Try to isolate our logic code from the Vue (Vue3) specific code. This means trying to move a lot of the logic code in libraries which are as much as possible independent from Vue, designing APIs for the Vue specific code with specific implementation for Vue
1a/ Make sure to make reusable code and not spread too much code inside the Vue templates or in Vue specific libraries.
1b/ Study if it would make sense to encapsulate Vue specific structure when we manipulate them in our logic code.
2/ Study web components and check if it would be possible to choose for our design system a web component based UI library (instead of a purely Vue based library). This is not so easy as the Vue libraries could be better on other criterias.
I’ve described some approaches around web components: https://design.xwiki.org/xwiki/bin/view/Proposal/Wiki30/Technologies/#HAboutWebComponents
2a/ Make some last verification that there is a not a magical web component based framework.
2b/ Abstract the design system so that we can more easily move to web components for it

This is important as we will probably need to migrate to a future Vue4 and we should help ourselves by grouping together the Vue3 specific code. It would also help if we made a wrong choice and should move to another framework.

Ludovic

+1

While I agree in principle, we also need to be careful to take into account encapsulation overhead, while could lead to degraded performances if done wrong (e.g., even too much Vue components nesting can lead to performance issues if not done correctly)

I started to have a look on this and:

  1. Web Components can be used (including reactiveness) inside Vue templates
  2. Some neat web Components libraries seems to exist. I think Vaadin is worth looking in more details for instance.
  3. It could also be interesting to check further how to implement Web Component with Vue 3
  4. It could also be interesting to study more lightweight libraries dedicated to the definition of Web Components (e.g. https://lit.dev/)

Probably over optimistic, but while Vue 3 was a major version upgrade, the Vue developers are aware of the migration pain and quoting them (When would Vue 3's end of life be? · vuejs/core · Discussion #7887 · GitHub):

When we do another major release, it will be much more modest and ship few breaking changes that will be easy to migrate.

We certainly don’t want to repeat the pain of Vue 2 → 3.

Some results from my tests:

  • exporting a Vue 3 component as a web component is seamless and is working well
  • re-using a Web Component in a Vue 3 component is seamless and is working well
  • composing together Web Components is more painful and requires more work as features covered by Vue 3 (e.g., reactivity, event handling) are supported by the Web Components APIs

Therefore, I suggest to:

  • use Vue 3 as our front end components framework
  • exporting our components as Vue 3 components to be used by extensions developing in Vue 3
  • exporting our components as Web Components to be used by extensions/third parties that do not depend on Vue 3

Also, this means that using a Web Components front end library is a possibility (see the corresponding proposal)

Sounds good. My only worry is Vue.js upgrades and how easy/hard they would be and how we would handle XWiki extensions (ie. how to not break backward compat if an extension is using, say, vue 3 and we move to vue 4).

Similar to how we have a backward-compatiblity strategy for XS, we would need something similar for the front end since the idea is to move a lot of code there.

One possibility is to say that extensions must be exposed as web components (and thus consumed as web components by Cristal). What it means is that Vue.js would be an internal implementation choice of Cristal, not known to extensions. I don’t know what this would mean though and what features extensions would be missing. More specifically I don’t know web components enough to know how we pass information between web components (and between vue.js and web components). For example, how would we share the Component Manager?

Thanks

According to Vue maintainers, the goal of Vue 3 was to build a more durable framework on top of learning from Vue 2. Meaning, no more major breakage like this.
But, I agree that in practice that does not mean much.

+1

Making the effort to publish our components as Web Components is there to address this. In addition to allow third party to re-use components without depending explicitly on Vue 3, this would also allow us to reuse all the work we are going to do with another framework if we ever need to migrate.
Note that this is not a perfect solution and we can end up in the situation we currently have with a lot of prototype code we have a hard time getting rid of in XWiki Standard (but in a more encapsulated way).

For that we’ll need to publish some library with a stable components API (i.e., a front-end xwiki-commons-component-api), allowing to access the Javascript “backend” components (we need to find a better terminology, the term “component” is very much overused) that must be used by (web/vue) components integrated with Cristal.