Page MenuHomePhabricator

RFC: API-driven web front-end
Closed, DeclinedPublic

Assigned To
None
Authored By
GWicke
Sep 5 2015, 12:09 AM
Referenced Files
F4287496: 2015-08-mdn-only-difference-site-chrome-logged-in-user.png
Jul 19 2016, 5:07 AM
F2681263: pasted_file
Oct 10 2015, 12:04 AM
F2680613: pasted_file
Oct 9 2015, 10:16 PM
F2680494: pasted_file
Oct 9 2015, 10:11 PM
F2680363: pasted_file
Oct 9 2015, 10:09 PM
Tokens
"Like" token, awarded by Akuckartz."Love" token, awarded by Milimetric."Mountain of Wealth" token, awarded by RandomDSdevel."Love" token, awarded by Renoirb."Like" token, awarded by Addshore."Like" token, awarded by Smalyshev."Love" token, awarded by Jhernandez."Like" token, awarded by fbstj.

Description

Problem statement

Our front-end and CDN architecture is facing formidable challenges. Close to 50% of our users are now using mobile devices in a wide range of specifications and form factors. Bandwidth conditions range from barely-connected 2G to gigabit fiber to the home. Use cases range from a quick definition look-up to immersive browsing with rich media and data-driven visualizations.

In response to the wide range of requirements, we have created a mobile site using MediaWiki's skin system, some content post-processing, and user agent based redirects. This site is now serving a sizeable chunk of our overall traffic, but it is ultimately still a fairly static server-side HTML skin. Its scaling relies on Varnish caching layers serving the vast majority of anonymous requests. These caching layers are fairly complex and inflexible. Significant customization of responses by user, device, or bandwidth conditions are typically not feasible without disabling edge caching altogether. This means that such customizations are currently limited to authenticated users, at the price of disabled caching and thus significantly higher request latencies.

Our native apps side-step a lot of these issues. They are pure API consumers, and perform most customizations in the client. This makes it a lot simpler to experiment with new ideas in the client, while still benefiting from caching of fairly static API responses. However, the vast majority of our users are using the web, and don't yet benefit from the same levels of performance and customization.

Proposed solution

This task proposes to leverage recent developments in the web platform to bring app-like levels of performance, customization and functionality to the general web experience. New browser features like ServiceWorkers have recently made it feasible to apply the API-driven front-end strategy to the web, without incurring the complexities and performance penalties of traditional single-page applications. While some of these web platform features are fairly cutting edge (ex: ~61% support for ServiceWorkers), they are generally designed to work as progressive enhancements, with server-side fall-backs facilitated by the convergence of client-side and server-side technologies around JavaScript. By gradually moving the bulk of per-request customization to clients, we should be able to use freed-up server-side resources to provide the same level of customization for the long tail of older clients, at latencies comparable to or better than those seen by authenticated users right now.

If proposal T106099 comes to be, and we have "page composition service" in production, we can extend its use case from the Wikipedia.org to also apply to MediaWiki-powered page views.

pasted_file (943×693 px, 129 KB)

Before we can this, however, we need to make significant changes to MediaWiki core.

Dependencies

Concrete steps:

Potential benefits

  • Performance
    • Authenticated views aren't currently cacheable, which means that editors are getting worse performance than anonymous users. An API-driven front-end lets us cache general content separately from per-user data, which means that authenticated views can be fully cached, bringing performance on par with anonymous users.
    • Potentially reduce first-view-in-session latency for returning visitors by keeping offline copies of static assets.
    • Potential for full offline support.
    • Through improved caching, reduce load on the app server cluster from cache misses, reducing hardware needs and environmental impact.
    • Composition can be implemented efficiently as string concatenation, without a need for expensive DOM parsing and -manipulation.
    • Potential to initialize VE without re-loading content.
  • Architecture
    • Introduce a clean API separation between data and UI/UX layer. This will drive API and content / data representation improvements, reduce complexity in the data layer, and accelerate front-end innovation from WMF & others.
    • Reduce code and test duplication by using the same JavaScript code for client-side & server-side content composition.
    • Clean no-JavaScript fall-back to server-side rendering without code duplication.
    • Reduce complexity in caching layers by separating per-user from per-page data.
    • Avoid complexity and performance issues of single-page apps.
    • Allows gradual testing of Parsoid HTML for page views, possibly as a beta feature.
  • Design / product
    • Potential to support more user customization and dynamically updated content elements without incurring cache fragmentation and increased latency.
    • Quicker iteration on the client, using technology front-end engineers are familiar with.

See also

Related Objects

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes

Discussed with @GWicke at Wikimania.

Building the service immediate for handling MediaWiki traffic is gonna be quite tricky since MediaWiki's skin system isn't ready for that right now.

  • Skin should be executable independent of global state. Ideally in a way that is able to share code with the Node service and/or in a way that can be exported through the API.
  • All hooks must be reduced to static conditions. (But sidebar links can still vary by page or user name, tabs may vary on page meta data and user permissions, etc.).
  • Need to be able to compile the skin layer down to a cacheable function (e.g. mustache template) that can be invoked with page and user data and produce the output - streamable.
  • Goal: With $wgUseFileCache enabled, the Skin layer should be cacheable independently of the page and applied at run-time. For deployments that use a CDN (e.g. Wikimedia with Varnish) one would use a separate service for the skin (the composition server from this RFC).
  • Benefits: 1) Response time for logged-in users comparable to that of logged-out users. 2) Skin updates apply in a unified way - at once. (Instead of gradually as different pages expire from the cache.)

I'd like to consider to first build a MVP for a non-MediaWiki use case (e.g. Wikipedia portal). We'll continue work on MediaWiki. Meanwhile, we can start making progress on the performance characteristics and implementation details of the composition server.

Krinkle renamed this task from [RFC] API-driven web front-end to RFC: API-driven web front-end.Jul 18 2016, 9:04 PM

I had spent some thoughts about this problem space.

Things I had in mind (e.g. WebWorker, a null theme only basic HTML patterns, and an API view) had been outlined.

In an ideal system, we want to optimize cache opportunity, lower same resource representation variants, keep editing capability and allow customization.

Let's assume we have:

  1. The article body HTML is the same regardless of which type of Web Browser you're using.
  2. We create cookies only to a context root Set-Cookie: Foo=...; Path=/ui/partials; ...

Then we can

  1. Create HTML "partial" renderer (e.g. what parsoid does)
  2. Patch up view to a given context.
  3. Use the exact same HTML to everyone regardless if user is signed-in or not
  4. If user is signed in (i.e. has a cookie matching Path /ui/partials) we patch up user actions snippets into the DOM asynchronously.

To illustrate my thoughts, I've made this screen capture.

2015-08-mdn-only-difference-site-chrome-logged-in-user.png (1×2 px, 719 KB)

PS: Imagine it's Wikipedia instead of MDN, please.

Thought it would be useful here.

@Renoirb, what you describe is indeed pretty close to what we have in mind. We have a bit more per-user variance in the UI, mostly related to editing functionality. For example, tabs for page deletions or protection are only shown to admin users with the appropriate rights. We also want to support varying the UI by device and network conditions. We are especially interested in improving support for poor network connectivity or even offline use. Some of these changes would be difficult to pull off cleanly & with good performance by using DOM patch-ups only.

Thankfully, once a user is logged in using a modern browser, we can leverage a ServiceWorker to compose content client-side. We are currently prototyping a basic composition / templating layer with streaming support. Current work is building on elematch, but @Krinkle is also looking into supporting mustache syntax. This should give us performance data for server-side use, where we would like to run the same serviceworker code using a faux environment like https://github.com/gwicke/node-serviceworker.

I should point out that given the mobile site currently supports a much smaller subset of functionality compared to desktop it might be a good place to iterate on some of the ideas here. Currently there is very little reason we need to vary cache for logged in users of the mobile site.

On the server side the UI only changes for logged in users in the following way:

  • talk link added
  • notification (echo) link added to top right
  • menu links / labels are different for logged in user (but all are rendered via JS - so this could easily be done at the JS level)

Viewing source of the mobile site, the main issues would be the following config variables shipped as inline js:

  • wgMinervaMenuData
  • wgUserName

As of last week, @GWicke and I have started to meet on a weekly basis to track progress on one of the first sub items of this task: T106099: RFC: Page composition using service workers and server-side JS fall-back.

Quick summary:

  • We're working on a more detailed draft and spec for the composition server (no code yet).
  • We've begun coding some of the low-level libraries required for the server. Relating to transform streams, Mustache support, and the ability to run the same code in both a ServiceWorker client and in a Node.js service.

See T106099 for more details.

A prototype service is now available at https://swproxy.wmflabs.org/wiki/Wikipedia. This is running unmodified ServiceWorker code in a server-side proxy environment equivalent to a Browser, and also installs the same ServiceWorker in modern clients. Resources are cached for offline use. See T106099 for the details.

  • clean Barack - 5.5s
  • w/ ServiceWorker, first load - 3s
  • w/ ServiceWorker subsequent load - 2s

Very nice!

Closing old RFC that is not yet on to our 2020 process and does not appear to have an active owner. Feel free to re-open with our template or file a new one when that changes.

This has been closed? Has an equivalent idea started under a different name?

A lot more work was done under T114542: Next Generation Content Loading and Routing, in Practice and eventually several projects were started up. Marvin was the official one, but there were other proofs-of-concept including https://github.com/jdlrobson/weekipedia and T101732 for ResourceLoader. Eventually Marvin was archived (T205170: Archive marvin) due to npm-related security issues and lack of on-going maintenance.

A more narrow proposal, driven by specific performance and user experience outcomes, exists at T140664: Achieve predictable MediaWiki routing and cacheable skin data as part of T302623: FY2022-2023: Improve Backend Pageview Timing.

This direction would see MediaWiki (re-)embrace principle of data flowing in one direction during page view generation, and as consequence allow better caching, and better separation of concerns, reducing the skin layer to a low level of (required) complexity, and allowing some skins (e.g. those WMF-deployed) to be so fast and simple that they could potentially be run near a CDN edge, if that were notably advantagous to latency (TBD). The steps along the way each come with significant performance and code quality benefits that pay off regardless of whether that last step is taken.