Change record status: 
Project: 
Introduced in branch: 
10.1.x
Introduced in version: 
10.1.0
Description: 

Drupal's CSS and JavaScript aggregation system previously worked by combining, processing and writing aggregate files within the HTML page request that requires the assets. While this processing did not take place once the aggregate had been written to disk, it added between hundreds of milliseconds up to over a second of processing to cold cache requests, since in many cases multiple CSS and JavaScript assets are required to serve a page.

This logic has been overhauled so that the main HTML request generates a URL with the filename for the asset plus sufficient information in the query string for a separate route (provided by system module) to then generate, serve, and write the asset to disk.

  • The libraries for the request that were used to generate the groups, and any already-loaded libraries (to exclude them from the aggregate)
  • The asset group
  • The theme for the request.
  • The language.
  • For javascript, whether the asset is rendered in the header or the footer (we divide js in two, then build groups for each).

Instead of a page request creating and writing several files before it can be sent to the browser, now the main page request just generates the URLs, and the actual CSS or JavaScript aggregate is individually created by PHP (and still written to disk assuming it's valid).

In a stampede/cold cache situation, this allows full HTML pages to be served significantly quicker with less blocking steps to serve each one. CSS and JavaScript assets are then individually requested and built by the browser if necessary. Since browsers request assets in parallel, multiple CSS and JavaScript assets can be built at once instead of in sequence, allowing the entire page as well as all of its assets to be served quicker overall.

Aggregate filenames are now based on the library definition instead of the contents of the file. However if a library does not have a version, the contents of the file will be additionally used to make up part of the hash. This allows custom modules and themes to invalidate browser and edge caches without having to increment their version each deployment.

This involves a number of API additions, deprecations and logic changes in the asset aggregation logic, detailed in a separate change record.

Impacts: 
Site builders, administrators, editors
Module developers
Themers

Comments

neograph734’s picture

It took me quite a while to figure out why my aggregates were not created and I got served all individual files instead.

Apparently this dynamic aggregation does not work in maintenance mode.

flocondetoile’s picture

Looks like yes. In maintenance mode, on a project with a lot of small files css/files, the page sent about a hundred request to the server, behind a reverse proxy, this last respond with 502 bad request (because the high number of simultaneous request done).

mxr576’s picture

It is good that in this revision this CR got a post update after #3370828: Ensure that edge caches are busted on deployments for css/js aggregates was fixed, but the related documentation about Adding assets (CSS, JS) to a Drupal module via *.libraries.yml also deserved an update about the current usage of "version" in library definitions since Drupal 10.1.2.

https://www.drupal.org/node/2274843/revisions/view/13464318/13535225