If you have parallel rendering of different page elements, then there is not one single PHP process to either:

1. hold a static of all assets.

2. collect stuff from all the render arrays on the page via #attached.

This means that sub-requests/blocks that require CSS or JavaScript (or want to add an RSS feed to the HTML head or whatever) are out of luck.

We discussed this at length at DrupalCon Munich and BADCamp, and currently have a draft of the following:

- all out-of-band stuff, all of them, need to use #attached, see #1839338: [meta] Remove drupal_set_*() drupal_add_*() in favour of #attached/response for out-of-band stuff

- #attached needs to work with the response object - probably we need a parallel or replacement implementation for things that return those instead of render arrays.

- when using a 'real' reverse proxy or SSI we came up with two approaches for getting the assets from the sub-requests to the main page:

1. All nested blocks need to declare the assets they need up front via a method, without having their render method called. So that the parent page can collect the dependencies without rendering the blocks. This would mean replacing #attached and having a method on block controllers or similar. However it's going to run into serious problems with something like FAPI where the form element might use #attached and the parent block callback can't know what's in there.

2. Everything uses #attached, then when rendering the block, we add some JSON to the HTML of that page. We then have a small script loader that finds assets in the JSON and adds them to the page so they're loaded asynchronously (or with RSS feeds/page title changes just adds/changes the HTML as required). This introduces a js dependency if you're using real sub-requests but it'd be pluggable in case someone comes up with something better.

For 'fake' reverse proxy, i.e. HttpCache, we could do the processing in the parent PHP process - so execute the sub-request, collect the #attached stuff, figure it out from there - very similar to how drupal_render() handles it now. The metadata for either approach is the same, it's just the processing of it by the 'parent' that's different.

Comments

Crell’s picture

Issue tags: +WSCCI

Tagging.

Wim Leers’s picture

Don't we have other, more complete/active issues for this right now?

(For something so important, it's scarily silent here…)

catch’s picture

Priority: Major » Normal

Actually I don't think we do, but it's also something that's not likely to get fixed in core at this point.

This issue is only about when sub-requests are actually different HTTP requests (whether it's ESI or CSI doesn't matter that much) - and they need a way to add assets to the parent page, despite the parent process having absolutely no knowledge of which assets were added (since it's not even hitting Drupal each time necessarily and nor might the sub-requests be).

That means this can be demoted to normal - assuming we have the rest in place to allow contrib to take care of this.

Wim Leers’s picture

Hm… I'm not sure I see how contrib can take care of this. How could contrib do that?

sdboyer’s picture

IMO, contrib can't do this right now. the only way to really cleanly tease out is to have a clear point of asset declaration that coincides entirely with the segment of html that is being deferred to *SI. we have pluggable processing now, but that doesn't mean we have the metadata necessary to know which assets should be deferred, or not. currently, we're far from it. that's pretty much an addressable blocks thing.

that's if we want to take the approach where the additional assets from these deferred html segments are added later as the CSI requests are being made (i can't imagine it working for SSI or ESI), rather than on initial response. we can still be fine if we front-load all assets. which strategy makes the most sense is gonna depend significantly on the nature of your application, i think.

Wim Leers’s picture

Indeed, this can only work for client-side includes (CSI), not SSI or ESI, because for client-side includes we can put the burden of "only load assets that the parent page doesn't already contain" on the logic that's requesting/rendering the includes.

We're handling that in #2469431: BigPipe for auth users: first send+render the cheap parts of the page, then the expensive parts.

Tempted to close this, but … I could imagine something like ResponseWithAssetsInterface plus a trait being an option — much like CacheableResponse(Interface|Trait).

Should we close this?

Crell’s picture

I would support closing this. There's newer issues and nothing really in this thread that's useful to mine.

Wim Leers’s picture

Status: Active » Closed (duplicate)