Design Systems Team/Server rendering background info

This is background information for the "Modern user interfaces for all users" TDMP, see T317270.

What server rendering is
The reason Codex components are currently only available in modern browsers is that they're implemented as client-side-only JavaScript, meaning the code that renders them executes in the user's browser. That will only happen if the user's browser supports a modern enough version of JavaScript and if the user hasn't disabled JavaScript. And it won't start happening until the JavaScript code has been downloaded, which could take a while on a slow connection.

If we want users of older browsers to be able to view and interact with user interfaces built with Codex, we need to render (a version of) the user interface on the server, so that the UI is already part of the HTML that the user's browser receives. This also helps users of modern browsers see (an initial and non-interactive version of) the UI faster, because they don't have to wait for the JavaScript code to be downloaded and executed. There are inherent limitations to how feature-rich and interactive a UI can be without JavaScript (or before JavaScript arrives), but in many cases a basic experience can be provided.

Possible approaches
Below are some approaches we have considered to the server rendering issue. These aren't meant to be universal approaches that we would use in every case: in practice, we'd likely use different approaches for different use cases.

Client-side only: don't render anything on the server
The simplest solution to this problem is to decide that we don't want to solve it at all. A user interface could be implemented entirely client-side, in JavaScript that runs on the client, and nothing would need to be rendered on the server. Users of older browsers would see an error message saying they can't use the feature. Users of modern browsers would be able to use the feature, but would initially see a "Please wait" message or some other placeholder before the UI loads.


 * (+) No extra work required to support no-JS or pre-JS environments
 * (-) The UI loads more slowly, and perceived performance is worse
 * (-) The UI can't be used in older browsers at all

Server-side only: don't use JavaScript-based interactivity
Some user interfaces may not need any interactivity, or can implement the limited interactivity they need in HTML and CSS. In this case, the UI can be rendered entirely on the server, no JavaScript is required, and the browser support and performance issues are moot. Most basic UIs in MediaWiki already work this way.

Codex does not currently support rendering components in PHP, and many components do require JavaScript-based interactivity. However, HTML+CSS-only implementations could be written for a subset of Codex components to support server-side-only interfaces.


 * (+) No performance or browser support issues
 * (-) Only suitable for simple UIs, not for complex/interactive ones
 * (-) Requires duplicate implementation of some Codex components

Progressive enhancement
In this approach, the UI is rendered on the server. This UI looks (mostly) like the full UI, but is not interactive. When (and if) JavaScript loads, it enhances the UI by adding interactivity, but doesn't change how the UI looks (or makes only minor changes).

This is how the web worked in the jQuery era, but modern web applications tend to be more complex, and modern web frameworks and libraries tend not to support this method. This method is most suitable for providing smaller amounts of interactivity in simpler UIs.


 * (+) Works in older browsers
 * (+) UI renders quickly, becomes interactive later
 * (-) Interactivity must be defined separately from UI layout
 * (-) Code complexity is difficult to manage when UI is complex and interdependent
 * (-) Not compatible with modern web frameworks/libraries

Separate server and client implementations
This is similar to the progressive enhancement approach in that the UI is initially rendered on the server. But instead of enhancing the existing UI, the JavaScript code destroys the server-rendered UI and replaces it with a client-side only UI that looks the same.

This approach essentially combines the server-only and client-only approaches, getting the best and worst of both. The UI is implemented twice, in different languages, and these implementations must be kept in sync for the transition from the server-rendered UI to the client-rendered UI to work correctly, otherwise visible jumps can occur or state information can fail to be preserved.


 * (+) Works in older browsers
 * (+) UI renders quickly, becomes interactive later
 * (+) Interactivity is defined together with UI
 * (-) UI implementation must be duplicated (in JavaScript and PHP)
 * (-) Prone to visible jumps and state management bugs

Vue server-side rendering (SSR)
Vue.js is a JavaScript-based UI framework that's primarily designed for client-side use, but it also supports rendering UIs on the server, through a feature it calls server-side rendering (SSR). Similarly to the "separate server and client implementation" approach, the client-side JavaScript takes over once it arrives and makes the UI interactive ("hydrates" it). But crucially, the server and client execute the same code, so no duplication is required.


 * (+) Works in older browsers
 * (+) UI renders quickly, becomes interactive later
 * (+) Interactivity is defined together with UI
 * (+) Code is written once to run in two environments
 * (-) Requires new infrastructure to connect Node.js-based Vue SSR with PHP-based MediaWiki code