Problem/Motivation

Thanks to #2469431: BigPipe for auth users: first send+render the cheap parts of the page, then the expensive parts a lot of brilliant work has gone into implementing the Big Pipe architectural concept into Drupal 8. What I understand of the work is that the critical path (the minimal set of markup that can be full cached and delivered quickly to user) can be determined thanks to the work done in annotating the cache contexts and cache tags of each render-able thing. Everything that is determined to be "expensive" is then placeholdered and replaced in a secondary process.

This allows the initial page to be delivered, extra data to be inserted into the page, and then the personalized, "expensive" components are triggered to get get their data.

Kind of like customizing a car. You buy a standard car and then get kits to replace the tires, stereo, and other things you want to replace. Getting the car can be easy, just get one from the lot. But getting the customized kits for accessories can be time-intensive since you need to get the ones that you like.

Anyway, as #2469431: BigPipe for auth users: first send+render the cheap parts of the page, then the expensive parts states in it's issue description, there are many ways that the replacement of placeholders can be handled. Web Components as defined by the emerging set of specifications (here: http://webcomponents.org/ ) can be compatible way. There are a few advantages and disadvantages of this approach and it would be worth our while to explore if the trade-off is in our favor.

Advantages:

1. Web components are built with HTML, JS, and CSS

Web components are built to define a set of inert markup that can be pushed into the DOM and later activated to drive a frontend component. Web Components are built to define their own behaviors and appearance. Portability is a key focus. The promise of building a component and then being able to reuse it over different projects is key here.

2. Web components are atomic and can be combined.

Many examples of component systems can be found on the interwebs. Using these comopnents together, developers can quickly build applications. While this is actually a pretty old concept the main difference here is how easy it is to make components and how developers can build their own component libraries instead of relying on slow-evolving vendor-driven ones.

3. Although incomplete browser vendor support exists today, the goal is to have these components supported natively.
Today polyfills such as found on http://webcomponents.org/ exist to ensure "evergreen" browser support (read: no oldIE) almost all browsers have annouced the intent to support or partial support for the standard. Chrome and Opera have full support, Firefox has partial, and MS Edge and Safari will eventually have partial support.

4. JS behaviors

The components themselves can take on duties such as observing when they need to update, reacting to other actions on the page, or on the server. Components can have 2-way data binding.

Disadvantages

1. Required to include another polyfill
Today the webcomponents.js polyfill is another 34 KB of javascript that would need to be loaded on any page a web component is needed. That's a 34 KB we wouldn't need if we didn't use Web components.

2. Speed
Today working with the polyfill is slow. Speed is improving but the sheer fact that you have to work with polyfills / secondary requests may be an issue. How much of an issue? We need to have numbers to put towards the performance question of Web Components and see if

3. Opinionated
Using web components is picking a path. While you can use web components with other frameworks (like Angular) there could be some scenrios where you don't want to work with them. I guess this is really a question about whether this should ever be brought into core or should be contrib-only.

See:
#2469431-108: BigPipe for auth users: first send+render the cheap parts of the page, then the expensive parts
#2469431-166: BigPipe for auth users: first send+render the cheap parts of the page, then the expensive parts

Proposed resolution

TBD

Remaining tasks

TBD

User interface changes

TBD

API changes

TBD

Data model changes

TBD

Comments

Wim Leers created an issue. See original summary.

cosmicdreams’s picture

Issue summary: View changes
skyredwang’s picture

Web Components are many things, but in the BigPipe case, we probably will only use two specific tools: Shadow Dom and HTML Imports.

By using these 2 tools in the implementation of BigPipe, we can completely eliminate Javascript in the process. However, we rely on Pollyfill (a JS library for browsers who don't support Shadow Dom natively). In other words, for modern browsers (ever green browsers), when they load a BigPipe page from Drupal, they will not use Javascript during this loading process.

For Drupal BigPipe maintainers, they don't need to think about JS anymore, another win.

Furthermore, Web Components are already production ready, but not mainstream yet. This list shows people who are building on Polymer (a framework based on Web Components): https://github.com/Polymer/polymer/wiki/Who's-using-Polymer%3F

Regarding tudo:

1. Change the markup of the placeholder to use "HTML Imports"
2. Change the markup of the "Expensive/Personalized HTML blocks" to be Shadow Dom compatible
3. Add Pollyfill library for backward compatibility support.

I am still learning more D8, maybe in a while, I will be able to write a patch or a new module for Web Components implementation of BigPipe.

wim leers’s picture

I am still learning more D8, maybe in a while, I will be able to write a patch or a new module for Web Components implementation of BigPipe.

That'd be great! :)

cosmicdreams’s picture

@skyredwang if you need code reviews / collaborators hit me up. I'm also keen on getting a patch that represents the advantages of Web Components.

wim leers’s picture

Version: » 8.x-1.x-dev

Looking forward to patches/prototypes :)

skyredwang’s picture

@Wim Leers, another thing related: HTTP/2 Push. When a request comes in, the BigPipe knows what parts are expensive. For HTTP 1.1, the client sends the requests for the expensive parts. But, with HTTP/2, it will be interesting that we take advantage of multiplexing and push to send the expensive parts automatically.

The performance gain will be the number of expensive parts on the page x the trip time it takes from client to server.

wim leers’s picture

Of course we'll use HTTP/2 Server Push for assets. We have the asset library dependency graph in D8 that allows us to automatically deduce which assets are worth pushing.

But that's 100% unrelated to BigPipe. It's only related in that BigPipe is possible thanks to finally knowing dependency metadata, and the same goes for HTTP/2 Server Push.

Note that I'm already working on this in collaboration with a university research project. More about that soon :)

skyredwang’s picture

I was talking about HTTP/2 push dynamic content. In the context of BigPipe. You send a static template first, then HTTP/2 push username, personalized flags, tokens, list of images, etc. I realize the current servers support for push is mostly for static assets.

It's always fun to read more of your R&D! Thanks for leading and pushing the boundary for our community.

wim leers’s picture

Project: BigPipe » Drupal core
Version: 8.x-1.x-dev » 8.2.x-dev
Component: Code » big_pipe.module
Category: Task » Feature request
Status: Postponed » Active

BigPipe has now landed in Drupal 8.1. It's now sufficiently stable/proven (~400 sites using it for the past few months) so unpostponing this. Feel free to post prototypes, research etc.!

cosmicdreams’s picture

Looking forward to it. In the meantime, browser support has grown. That should be in the research reporting as well. Let's shoot for March 21 as an arbitrary deadline for putting this all together.

@skyredwang does that work for you / can we get together to organize? Anyone else want to contribute?

Woohooo! Let's go!

skyredwang’s picture

I am spending full time on Commerce 2.x related stuff on D8 this month. So, I won't be able to do anything with Web Components soon. But, I am trying to get a GSoC student to work on that https://groups.drupal.org/node/508466#project4

tic2000’s picture

It seems the browser vendor reached some consensus and WebKit is starting implementing custom elements https://lists.webkit.org/pipermail/webkit-dev/2016-March/027995.html

Also you can test for custom elements support and load the polyfill only if needed with something like


var webComponentsSupported = (
  'registerElement' in document &&
  'import' in document.createElement('link') &&
  'content' in document.createElement('template')
);
if (!webComponentsSupported) {
  var script = document.createElement('script');
  script.async = true;
  script.src = '/bower_components/webcomponentsjs/webcomponents.js';
  script.onload = finishLazyLoading;
  document.head.appendChild(script);
}
else {
  finishLazyLoading();
}
function finishLazyLoading() {
  // do something;
}
wim leers’s picture

Yep, https://twitter.com/ryosukeniwa is tweeting about that quite often — he's working on the WebKit implementation.

cosmicdreams’s picture

Another excellent public signal https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/EDxhDZ-...

This community post points to the consensus that has been reached on custom elements (the key piece we're talking about here)

wim leers’s picture

Version: 8.2.x-dev » 9.x-dev

I think it's misleading at this point that this is marked for 8.2.x-dev.

It's clear this is still at least years away from being supported by a sufficient margin of browser share.

It's not remotely clear how BigPipe would ever use Web Components. Especially since it'd largely defeat the purpose of BigPipe: have a single response stream additional content as soon as it becomes available. Using Web Components implies using multiple requests.

So, moving to 9.x.

wim leers’s picture

Title: Look into using Web Components for BigPipe » Add a WebComponentStrategy
Component: big_pipe.module » render system

Furthermore, the IS says:

there are many ways that the replacement of placeholders can be handled

… this gets to the gist of what this issue is about: a new placeholder strategy, that doesn't render placeholders on the server side and blocks until they're all done (like \Drupal\Core\Render\Placeholder\SingleFlushStrategy does), nor renders placeholders on the server-side in a non-blocking way (like \Drupal\big_pipe\Render\Placeholder\BigPipeStrategy does). Instead, it'd map each placeholder to a web component … but then things become fuzzy: does it important fully rendered HTML? Or does it come with a HTML template + JS, with the JS taking care of filling in the variables in the template?

That just shows that this is not about BigPipe, this is about providing a new placeholder strategy that is independent of BigPipe, and is simply a different choice.

This is also basically what the GSoC project that skyredwang proposed and is mentoring (and that I'm co-mentoring) is about. See https://blog.radiumz.org/en/post/33/gsoc-2016-more-app-experience-drupal and https://drive.google.com/a/acquia.com/folderview?id=0B_ZsBQ4mpbKQN29peGV....

Retitling and moving accordingly.

catch’s picture

Project: Drupal core » Drupal core ideas
Version: 9.x-dev »
Component: render system » Idea

Moving to the ideas queue.

yoroy’s picture

Status: Active » Postponed (maintainer needs more info)

I *think* some of this is already being worked on for core?

nod_’s picture

Status: Postponed (maintainer needs more info) » Active

time to resurface this?

shaal’s picture

@nod_ Yes please

brianperry’s picture

This is relevant to my interests 🙂

Was interesting reading the history here. Obviously web component support and adoption has increased greatly since this issue was created. Polyfills for IE 11 are still a concern, but with IE 11 support being dropped in Drupal 10 that could potentially not be a concern for Drupal 10 and beyond.

Using Big Pipe to address this was also an interesting concept. In fact, there has been recent work to try to solve SSR for web components, and it is conceptually similar in some ways. As part of the Lit 2.0 release there is also an experimental SSR package: https://github.com/lit/lit/tree/main/packages/labs/ssr which server renders an initial container, and can rehydrate on the client side. This is based on a Declarative Shadow DOM feature https://web.dev/declarative-shadow-dom/ which is shipping in Chrome and Edge and is also not Lit specific from what I understand. With any luck browser support will increase in the future.

(A bit of a tangent, but there is a lot that I like about Astro's partial hydration concept: https://docs.astro.build/core-concepts/component-hydration. The Islands Architecture https://jasonformat.com/islands-architecture/ might also be relevant to what we're discussing here)

There is also some relevant work in happening in contrib.

I maintain the Generic Drupal Web Components (GDWC) project https://www.drupal.org/project/gdwc. The long term goal there is to have a library of generic web components that can be used both in decoupled projects that source data from Drupal and also in Drupal's traditional rendering layer. A menu component was built out in support of the Decoupled Menus Initiative https://gdwc.netlify.app/?path=/story/components-menu--primary. Next step here is building out more components. That has stalled a bit - from my perspective in order for this to scale for decoupled sites there needs to be a better solution to state management. I have that just about unblocked which should hopefully get things moving again.

There are also a couple of noteworthy projects related to Drupal integration and component distribution. Neither are specific to web components, but both should play nicely with them.
- Component: https://www.drupal.org/project/component - defines components in yaml and creates component blocks. Module contains web component examples.
- JS Widgets: https://github.com/js-widgets/js-widgets - uses an externally hosted registry defined in json and makes widgets available to Drupal via widget_instance and widget_ingestion modules.

There are almost certainly other projects I'm forgetting to mention...

All of this to say that having a clear web component (and possibly web component distribution) strategy for Drupal would be fantastic.

effulgentsia’s picture

Great writeup in #23!

As I understand it, the scope of this issue is just about adding a rendering strategy to core's BigPipe module to implement placeholders via web components rather than the current BigPipeStrategy, which uses <span> tags and custom AJAX code to replace those spans. If so, then +1 to that idea for Drupal 10, where we don't have to cater to IE11 anymore. Seems like it would be a clearer implementation, leveraging the appropriate web standards and browser capabilities. I'm not clear on whether it would offer any benefits other than code clarity (e.g., I don't know that ShadowDOM is valuable for BigPipe), but the code clarity benefit alone seems more than worth it to me.

All of this to say that having a clear web component (and possibly web component distribution) strategy for Drupal would be fantastic.

+100 to this! I think that's a separate scope than this issue though. Would you be willing to open a new Ideas issue for it if there isn't one already?

effulgentsia’s picture

Title: Add a WebComponentStrategy » Render BigPipe placeholders as a web component that can asynchronously populate itself rather than as a <span> that gets replaced by a separate AJAX command

Retitling this issue to what I think it's about, though please correct me if I'm misunderstanding it.

brianperry’s picture

#18 seemed to change this to be focused around a web component strategy rather than anything related to big pipe. I also don't necessarily have a problem with creating a new ideas issue for this if the history makes things confusing, I just think we'd ideally zero in a little bit more specifically on what that idea is first. Right now my idea is mostly just that we should have an idea :)

effulgentsia’s picture

Title: Render BigPipe placeholders as a web component that can asynchronously populate itself rather than as a <span> that gets replaced by a separate AJAX command » As an alternate to BigPipe, add a PlaceholderStrategyInterface implementation that renders placeholders as web components

Hm, ok, retitling based on #18, I think.

For the larger scope of #23 / #26, I opened #3230518: Figure out how we want to incorporate web components in Drupal 10.

catch’s picture

Project: Drupal core ideas » Drupal core
Version: » 11.x-dev
Component: Idea » render system

I moved this to the ideas queue before, but I think this actually can just be a feature request against core again.

I think the idea here is:

1. Add a new placeholder strategy, which would be in the render system, not in bigpipe module.

2. Consider whether to switch bigpipe to use that strategy.

From working in bigpipe recently, there are a lot of considerations to #2 - bigpipe is very much reliant on the AJAX system for communicating assets and (soon) messages, but that would make it a good test case for the new strategy even if we eventually decided against changing it.

wim leers’s picture

I think using BigPipe as a testbed/proving ground makes sense. 👍

In fact, there's nothing stopping us from supporting both approaches simultaneously in BigPipe:

  1. server-side rendered markup that BigPipe pushes to the client
  2. client-side rendered markup for which BigPipe pushes the necessary inputs for to the client

The latter would be an alternative way of achieving #2632750: Interface previews/skeleton screens through optional "preview" or "placeholder" templates (see BigPipe placeholder content can now be customized), with virtually zero server-side logic — it could all be done in JS/CSS!

But I have the feeling that is not really what you meant? 😅

catch’s picture

I was looking at #2602726-4: As an alternate to BigPipe, add a PlaceholderStrategyInterface implementation that renders placeholders as web components which looks interesting for being no-js, but it looks like there's no way to do HTML includes without a separate HTML request, so we'd be swapping a small amount of JavaScript for a large amount of PHP requests with that, which would not be a good trade-off.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.