Problem/Motivation

Postponed on #1945262: Replace custom weights with dependencies in library declarations; introduce "before" and "after" for conditional ordering

It is not possible to set an arbitrary aggregation group on JS assets.

The feature was removed when we switched to put all assets in libraries #1996238: Replace hook_library_info() by *.libraries.yml file with the idea that this shouldn't be used for ordering js files between each others because dependencies should be explicitly declared. This worked as intended, many if not all devs use libraries and declare their dependencies.

Not allowing to set a group now prevent us from making further optimisation possible (and it did at the time too #1996238-67: Replace hook_library_info() by *.libraries.yml file with less impact)

Proposed resolution

I think there are 2 steps:

  1. Enable the old behavior to make sure the perf hit of ckeditor5 is as small as possible
  2. Implement a proper solution (possibly reviewing the whole lifecycle of libraries, a few things are missing IMO)

The intent is for module developer to be able to set an aggregation group on their assets to bundle them independently from the other files as a performance optimisation, it might enable advagg to do some more fancy work too.

This will impact dependency resolution, a group can only be added below all the aggregated group dependencies (in case there are dependencies external to the aggregation group, like a script that depends on core/drupal or core/jquery within the group)

Remaining tasks

Agree and come up with the steps to get there.

API changes

Allow setting a group key in library definition, or something similar.

Issue fork drupal-3232810

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

nod_ created an issue. See original summary.

nod_’s picture

Status: Active » Needs review
bnjmnm’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

I'm spending some time with Drupal\Core\Asset so I can provide an informed opinion on this. Even if it's just a "looks good!", it'll be an informed "looks good!". Although I'm still familiarizing myself with everything Asset, a few things come to mind:

  1. There's a default value that can be overridden by a config setting. This should have test coverage, perhaps something analogous to \Drupal\Tests\Core\Asset\CssCollectionGrouperUnitTest::testGrouper? Clearly there's some missing coverage as the the MR changes functionality but all tests continue to pass
  2. The aggregation itself should be tested too. Looks like that may be a reasonably simple addition to \Drupal\KernelTests\Core\Asset\AttachedAssetsTest::testAggregation? Aside from basic coverage, this seems additionally important as there are other chunks of code dealing with JS Assets that may be assuming JS does not have configurable groups. (\Drupal\Core\Asset\AssetResolver::getJsAssets seems like it may do this, but tests would prove/disprove it). Such a test would essentially confirm it will work for CKEditor 5 so we don't have to open additional followups while working on #3224261: [PP-2] Front-end performance: concatenate CKEditor 5 JS assets for every unique configuration
  3. I don't have a strong opinion on whether or not this should be considered, but it merits mention: Before group was un-API'd, it was understood that its value informed the loading weight. This re-introduction of group is only for aggregation purposes, so perhaps the config property could be named something different likeaggregation_group? Even though the value ultimately gets assigned to group in the stored config, the outcome is different from what group previously did.
nod_’s picture

That is a good point, it should probably be called something else to avoid confusion. It can still be used to order assets so kinda dangerous as well too. Might go with the 'tag' thing I mentioned in the other issue see how it goes.

Wim Leers’s picture

Issue tags: +front-end performance
Wim Leers’s picture

+1 to the remarks in #4.

I think this basically means that \Drupal\Core\Asset\AssetCollectionGrouperInterface::group()'s implementation freedom becomes more restricted — but the existing interface and API does not specify very strictly (or very clearly…) the existing responsibilities and freedoms either. (Mea culpa!)

An even better approach? Perhaps too abstract and too much magic?

More generally, I am not sure this change is necessary. We could also choose to instead make the existing grouping logic smarter. For example, if a particular asset library (dependency) subtree is tightly related, then we could choose to put that in a group of its own. See https://en.wikipedia.org/wiki/Component_(graph_theory). That is tricky though: where does one draw the boundaries?
So … I think I agree that this change is probably the simpler (and "less magical") choice.

But I still wonder if there's a better approach here. In the end, this declaring of some group X on a bunch of asset libraries is essentially the same as what I just described in the previous paragraph: marking the assets in a particular asset library subtree — i.e. those with strong connections to each other and weak (or usually no) connections to other asset libraries.

I wonder if we should instead declare the starting point (i.e. the root) of a particular asset subtree as deserving its own group/aggregate? 🤔 But that too leaves the "where does one draw the boundary?" question 😬 And again would involve some level of magic.

Stepping stones towards a better approach?

To get more concrete instead of describing these abstract ideal states: I wonder what the output would be for a script that analyzes the entire list of Drupal core's asset libraries and lists all asset libraries that: A) are leaves (have no dependencies), B) have >1 dependents. For this list, sort them by most dependents to least, and show the dependents count.

For ckeditor5/ckeditor5 (or when it's in core: core/ckeditor5), it would be listed as one of the topmost of these, and would have dozens of dependents.

I think this information might lead us to see a way forward to a better approach?

nod_’s picture

+1, that's what i had in mind. Do some graphviz output of the dependencies and view if there are obvious groups that stands out.

I do think we need an additional level though. It'd be nice to be able to manipulate an group that is an aggregate of several libraries as a library itself (or some kind of virtual file that contains the aggregate of all the libraries), so that if we put preprocess: false on that library aggregate, it ends up in it's own file. That would also mean that some of the setting that we put on individual files could be added at the library level.

To me that was the purpose of the #3227837: Optimize aggregation grouping issue, with this one only being the specific issue for the implementation of the fix on the cke5 side of thing.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

nod_’s picture

We could also look at how css layers are implemented too, it's similar in some ways. https://www.bram.us/2021/09/15/the-future-of-css-cascade-layers-css-at-l...

We allow defining aggregation groups and we let themes/modules define which order those aggregate groups should be added on the page, or if several groups should be combined into a single one if necessary. As long as we give control over what happens with the groups i don't see a risk of having contrib define arbitrary groups. By default we can have those groups ignored, or put all unconfigured groups in a single aggregate. And the relative order of the groups instead of going with weights, we let the developer declare the order they want the aggregates in, like the css layers?

nod_’s picture

Version: 9.4.x-dev » 10.0.x-dev
catch’s picture

And the relative order of the groups instead of going with weights, we let the developer declare the order they want the aggregates in, like the css layers?

The order should really be determined by library dependencies.
Which would mean we need #1945262: Replace custom weights with dependencies in library declarations; introduce "before" and "after" for conditional ordering first.

There would then still be a possibility of someone declaring groups that are incompatible with dependencies:

library 1 - group 1

library 2 - depends on library 2, group 2

library 3 - depends on library 2, group 1

For this case, there's a couple of options:
1. Validate it (during discovery?) and throw an exception/log an error. Ignore the group. I think this would be good if we can do it.

2. Create three aggregates (messy):
Aggregate A - group 1
Aggregate B - group 2
Aggregate C - group 1

Wim Leers’s picture

1. Validate it (during discovery?) and throw an exception/log an error. Ignore the group. I think this would be good if we can do it.

+1

catch’s picture

Title: Allow setting aggregation groups for js files in library definitions » [PP-1] Allow setting aggregation groups for js files in library definitions
Status: Needs work » Postponed
Wim Leers’s picture

Ohhhhh, long time no see, #1945262: Replace custom weights with dependencies in library declarations; introduce "before" and "after" for conditional ordering, but that literally came up earlier today in a meeting with the CKEditor 5 team, as a more elegant solution to a tricky plugin loading problem that @lauriii had been battling! :D

catch’s picture

Issue summary: View changes
Issue tags: -JavaScript +JavaScript

Adding the issue this is postponed on to the issue title because I couldn't figure it out until I read my own comment...

Version: 10.0.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.