Problem/Motivation
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:
- Enable the old behavior to make sure the perf hit of ckeditor5 is as small as possible
- 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
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:
Comments
Comment #3
nod_Comment #4
bnjmnmI'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 everythingAsset
, a few things come to mind:\Drupal\Tests\Core\Asset\CssCollectionGrouperUnitTest::testGrouper
? Clearly there's some missing coverage as the the MR changes functionality but all tests continue to pass\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 configurationgroup
was un-API'd, it was understood that its value informed the loading weight. This re-introduction ofgroup
is only for aggregation purposes, so perhaps the config property could be named something different likeaggregation_group
? Even though the value ultimately gets assigned togroup
in the stored config, the outcome is different from whatgroup
previously did.Comment #5
nod_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.
Comment #6
Wim LeersComment #7
Wim Leers+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?
Comment #8
nod_+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.
Comment #10
nod_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?
Comment #11
nod_Comment #12
catchThe 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
Comment #13
Wim Leers+1
Comment #14
catchIf I'm wrong change it back, but I think this should be postponed on #1945262: Replace custom weights with dependencies in library declarations; introduce "before" and "after" for conditional ordering.
Comment #15
Wim LeersOhhhhh, 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
Comment #16
catchAdding the issue this is postponed on to the issue title because I couldn't figure it out until I read my own comment...