Problem/Motivation
Follow-up from #769226: Optimize JS/CSS aggregation for front-end performance and DX which is very old but we still have some of the same problems. #977844: Remove the 'every_page' option for CSS/JS assets: it is confusing, even damaging also has lots of background.
This is a spin-off from #2989324: Allow CSS to be added at end of page by rendering assets with placeholders since we will need to do this issue to make that one effective.
Postponed on #3445285: Add extra page request to the across pages asset performance test and #3439017: Umami page.tpl.php breaks block placeholders.
Drupal's CSS and JavaScript aggregation puts files into one or two aggregates per page. A major problem over the years has been duplication between aggregates.
i.e. visit the front page of the site, and the aggregate will contain a mixture of site-wide CSS and CSS that is specific to the front page. The visit a node page, and the aggregate will contain a mixture of site-wide CSS and CSS that is specific to the node page. The result can be that instead of downloading 50kb +10kb + 10kb of CSS you're now downloading 60kb + 60kb of CSS. The same problem exists for JavaScript.
Steps to reproduce
Even with BigPipe enabled, a lot of content is not rendered via placeholders, we currently only do that to improve cache hit rates, not to optimize asset handling. Therefore you can see the original problem described in #769226: Optimize JS/CSS aggregation for front-end performance and DX with Umami.
1. Browse to the front page - note the three CSS aggregates created.
73K css_AD1Hn2WFqLD7fmsN-QRSIv7W-iE1t07DC546l3sXBT8.css
33K css_F6ua64ArNPnvFjJTt6gRulGbIdGiJ7kJGb2LMNHs2Xo.css
4.2K css_oSlWcVKLLDVnJnov5RFzD9u_RLcNFMy31r61RbJCgbY.css
2. Click on 'Articles' - note
73K css_AD1Hn2WFqLD7fmsN-QRSIv7W-iE1t07DC546l3sXBT8.css
33K css_F6ua64ArNPnvFjJTt6gRulGbIdGiJ7kJGb2LMNHs2Xo.css
72K css_ktGu9CM5DvTepixYiS5mZ3xk0zTeqc0toanu-L3COMk.css
4.2K css_oSlWcVKLLDVnJnov5RFzD9u_RLcNFMy31r61RbJCgbY.css
Those 72k and 73k aggregates are nearly identical, except for the Umami banner SDC (which is a content block near the top of the front page).
Proposed resolution
BigPipe already has a mechanism to fix this problem, but in practice it doesn't actually fix it in a lot of cases yet.
When BigPipe is enabled, assets that are attached within in process of rendering a placeholder are rendered with the placeholder instead of added to the main aggregates that are sent with the initial page response.
The page starts to render with only the CSS needed for the initial response before the placeholders are rendered. This allows this CSS to be downloaded and parsed while the rest of the page is still rendering, allowing for faster First Contentful Paint and Largest Contentful Paint.
Assets that are only needed by placeholders get put into their own placeholder-specific aggregates. This would mean for example that if you had a js slideshow that only shows up on the front page below the fold, the CSS and JavaScript would get loaded only once everything above the fold has been rendered (give or take).
Because the slideshow CSS and JS is now in its own aggregate, if you browse to the front page, then another page on the site, where the only different assets are rendered via placeholders, the 'main' aggregates (also the ones the block the initial page render) are cached. No more downloading of duplicate CSS rules in a different file.
With the Umami banner situation, if we force the banner block to be rendered as a BigPipe placeholder, then the assets for that placeholder end up in their own aggregate, and there is no more duplication between the front page and articles pages.
The MR is a proof of concept and not committable, however one possibility would be for block_content module to alter hook_block_build_block_content_alter() so that all of its blocks get #create_placeholder => TRUE.
We should also do the same for all views blocks.
Once we've made this change, if we then do #2989324: Allow CSS to be added at end of page by rendering assets with placeholders then this will also have the same effect for non-BigPipe responses - either when the module is off, or for anonymous users.