- Issue created by @ambient.impact
- 🇨🇦Canada ambient.impact Toronto
Added more detail, links to relevant Drupal core and Turbo code, and an example of one hack that seems to work around the issue (though not fixing the underlying problem).
-
Ambient.Impact →
committed d49260b9 on 2.x
Issue #3414538: Added refreshless_turbo_update_10202() to rebuild.
-
Ambient.Impact →
committed d49260b9 on 2.x
-
Ambient.Impact →
committed 9ed32e82 on 2.x
Issue #3414538: refreshless_turbo/js/refreshless.js data-turbo-track="...
-
Ambient.Impact →
committed 9ed32e82 on 2.x
-
Ambient.Impact →
committed 95134ffb on 2.x
Issue #3414538: preprocess: false on refreshless_turbo/js/refreshless.js
-
Ambient.Impact →
committed 95134ffb on 2.x
-
Ambient.Impact →
committed 8ce2c37d on 2.x
refreshless_turbo/js/ajax.js: Merge .use-ajax into once(): This may...
-
Ambient.Impact →
committed 8ce2c37d on 2.x
-
Ambient.Impact →
committed 21ff6396 on 2.x
Issues #3414538 & #3399243: Fix drupalSettingsLoader w/ JS aggregation.
-
Ambient.Impact →
committed 21ff6396 on 2.x
- Status changed to Postponed
9 months ago 12:27am 24 February 2024 - 🇨🇦Canada ambient.impact Toronto
Setting to postponed for now; we can clearly state that a known limitation of this Turbo implementation is that JavaScript aggregation should be off or weird things will happen which should be fine for a dev or alpha release; when we start getting to beta, we'll need to implement the longer term proposed resolution in some way.
- 🇬🇧United Kingdom catch
One possibility would be to track $ajax_page_state in session, and then maybe in a middleware, take what's in $_SESSION and fake the query parameter (probably merging with whatever's already in there just in case), then Drupal won't load any of those already-loaded libraries.
- 🇨🇦Canada ambient.impact Toronto
That may work, yeah, but I'm wondering if forcing a session for all users - including anonymous users - is going to have a noticeable performance hit. By default, Symfony doesn't start a session until there's something in the session to track (like in this case the Ajax page state) for performance reasons. That said, we do force a session for all users on Omnipedia to track the last few wiki pages a user has visited so that the random page controller knows not to pick something you've just seem, and that seems to perform well enough. If we do start sessions for all users, it would be a good idea to require the core `page_cache` module is uninstalled, because it'll prevent a session being started if a page is already cached - it took me far longer than I would have liked to figure out it was why our random page controller would sometimes redirect to the same page over and over for anonymous users.
- 🇬🇧United Kingdom catch
Might be possible to set it in a cookie instead as well, could still be read in a middleware.
- 🇨🇦Canada ambient.impact Toronto
I haven't messed around with any middleware as of yet so I'm not experienced with that but I like the idea. If anyone wants to create a basic prototype I'd be happy to test it out. Sorry about the slow replies; I'm busy with a bunch of stuff at the moment but checking in every so often.
- 🇨🇦Canada ambient.impact Toronto
So I tried to implement a solution based on @catch's idea and it sort of works but not quite. It doesn't yet have a cache context to vary by and it breaks Turbo since the Turbo JavaScript isn't found on the page so Turbo does a full page load, and I feel like piggybacking on
ajaxPageState
might not be worth the potential headaches down the road if that changes.To do list/ideas
- Implement a cache context that varies based on a hash or compressed URL query string because we'll likely need to add that to the page
#cache
. - Port over some of the 1.x
refreshless_page_state
logic and don't spoof or useajaxPageState
. - Also don't forget
RefreshlessRenderer::validatePreconditions()
for security from the 1.x branch. - Turbo and RefreshLess stuff needs to be handled separately and excluded from being removed on subsequent pages because doing so causes Turbo to relinquish control and let a full page load occur. We may have to decorate another one of the core asset services to group the RefreshLess and Turbo stuff into its own aggregate since setting it all to
preprocess: false
isn't great. - Implement the PHP logic somewhere to exclude the already loaded libraries somewhere; our decorated
AssetResolver
would make the most sense since it's central to the whole process.
Core stuff to use as reference
- Implement a cache context that varies based on a hash or compressed URL query string because we'll likely need to add that to the page
- Status changed to Needs work
about 2 months ago 9:55pm 24 September 2024 - 🇨🇦Canada ambient.impact Toronto
Alright, so I think I have it mostly working. It should now be aggregating and
attaching only what's not already on the page, with the following caveats/problems yet to be resolved:- Our module JavaScript is set to
preprocess: false
for now because it doesn't seem possible to group ourselves into a separate aggregate; see ✨ [PP-1] Allow setting aggregation groups for js files in library definitions Postponed . Ideally, we would be grouped into one aggregate that contains just therefreshless_turbo/refreshless
andrefreshless_turbo/turbo
libraries so that we could take advantage of core's minification and gzipping. - We have to special case the
refreshless_turbo/refreshless
andrefreshless_turbo/turbo
libraries to ensure Turbo is always attached even with the additive libraries logic, but never attached or aggregated more than once because bad things happen when Turbo loads and evaluates itself a second time. - There's some duplicate logic between the middleware and our decorated asset resolver that I'm not happy with but I couldn't get it work well enough without it. I'll probably rewrite some of it into an attachments processor (see the HTMX module's
HtmxResponseAttachmentsProcessor
) to hopefully remove the duplication. - This re-introduces the same CSS specificity symptoms as seen in
🐛
Turbo: CSS files merged into the on Turbo navigation always appended instead of preserving full page load order, causing CSS specificity issues
Active
but now when aggregation is enabled as well: the cause now seems to be that the base theme's (Claro) CSS for dropbuttons and vertical tabs is additively aggregated (since they're defined in separate libraries and not on every page) while Gin compiles dropbuttons into its big
gin.css
that gets attached to every page and uses a fixed weight value on itstabs.css
library definition rather than listing Claro's as a dependency. The best course of action may be to rework the additive aggregation so that it only applies to JavaScript and not libraries as a whole, leaving CSS to aggregate as it did before, non-additively; this may be doable via our decorated asset resolver in thegetCssAssets()
method by checking if the current request is a Turbo request and then temporarily removing the already loaded libraries, calling$this->decorated->getCssAssets()
, then restoring the already loaded libraries before returning the CSS assets. - It's unclear if this needs a cache context because this seems to be working with caching, but my gut is saying that we should have a cache context and set up a clear distinction between a full page load and a Turbo/additive load, because there's a bunch of stuff in the code that just YOLOs it without a care which might backfire in the future.
So it still needs work but some progress has been made. The hardest part of this is working without an easy way to visualize what libraries are being (additively) aggregated and attached to a page. Setting up some tests for that would help, but I would also want to implement console logging of what new libraries get added, much like the 8.x-1.x branch has, and may something a bit more visual would help as well.
- Our module JavaScript is set to
- 🇨🇦Canada ambient.impact Toronto
Updating title as we now know what needed to be done and why.
- 🇨🇦Canada ambient.impact Toronto
Heavy rewrite of issue summary reflecting current understanding of the problem and solution.
- 🇨🇦Canada ambient.impact Toronto
Added remaining tasks and follow up tasks.
- 🇨🇦Canada ambient.impact Toronto
Reordered "Remaining tasks" and "Follow up tasks", and moved some stuff between them where they make more sense.
- 🇨🇦Canada ambient.impact Toronto
Link to 📌 Turbo: Automated tests Active for test details.
- 🇨🇦Canada ambient.impact Toronto
Added a few remaining tasks from my comments.
- 🇨🇦Canada ambient.impact Toronto
Added References section with links to the HTMX module.
- 🇨🇦Canada ambient.impact Toronto
Removed session item (not actually true) and added page cache request policy item.
- Merge request !9Issue #3414538: Turbo: Implement additive JavaScript aggregation to prevent multiple evaluation → (Merged) created by ambient.impact
-
ambient.impact →
committed be6f7324 on 2.x
Issue #3414538: Added missing core/once dependency to fix tests.
-
ambient.impact →
committed be6f7324 on 2.x
-
ambient.impact →
committed 656a0a24 on 2.x
Issue #3414538: Ajax page state theme_token output only if diff theme:...
-
ambient.impact →
committed 656a0a24 on 2.x
-
ambient.impact →
committed 0591e0fc on 2.x
Issue #3414538: Updated readme.md with current state of JS aggregation.
-
ambient.impact →
committed 0591e0fc on 2.x
-
ambient.impact →
committed 48c15bac on 2.x
Issue #3414538: Additive libraries middleware now runs after core Ajax...
-
ambient.impact →
committed 48c15bac on 2.x
-
ambient.impact →
committed c13e9fb0 on 2.x
Issue #3414538: Additive libraries middleware now uses context service.
-
ambient.impact →
committed c13e9fb0 on 2.x
-
ambient.impact →
committed 21c73950 on 2.x
Issue #3414538: Force reload if page restored in possible broken state.
-
ambient.impact →
committed 21c73950 on 2.x
-
ambient.impact →
committed 2b6227e1 on 2.x
Issue #3414538: Add a service to detect Turbo requests + cache context.
-
ambient.impact →
committed 2b6227e1 on 2.x
-
ambient.impact →
committed cf9a47a0 on 2.x
Issue #3414538: Add Turbo reload <meta> for aggregation config changes.
-
ambient.impact →
committed cf9a47a0 on 2.x
-
ambient.impact →
committed 1a519967 on 2.x
Issue #3414538: Cleaned up and documented Javascript::outputPageState().
-
ambient.impact →
committed 1a519967 on 2.x
-
ambient.impact →
committed 55efc419 on 2.x
Issue #3414538: Updated JS aggregation readme section now that it works.
-
ambient.impact →
committed 55efc419 on 2.x
-
ambient.impact →
committed aa0ab207 on 2.x
Issue #3414538: Enabled aggregation for our own JS if core patched: See...
-
ambient.impact →
committed aa0ab207 on 2.x
-
ambient.impact →
committed 947b0044 on 2.x
Issue #3414538: Drupal settings loader no longer needs once().
-
ambient.impact →
committed 947b0044 on 2.x
-
ambient.impact →
committed 53bcce28 on 2.x
Issue #3414538: Added update hook to rebuild container/libraries.
-
ambient.impact →
committed 53bcce28 on 2.x
-
ambient.impact →
committed 8e8de278 on 2.x
Issues #3414538 & #3399314: Additive JS no longer breaks library CSS.
-
ambient.impact →
committed 8e8de278 on 2.x
-
ambient.impact →
committed 2134552e on 2.x
Issue #3414538: Rename header to indicate Turbo.
-
ambient.impact →
committed 2134552e on 2.x
-
ambient.impact →
committed adf57ecc on 2.x
Issue #3414538: Cookie and head constants + better documentation.
-
ambient.impact →
committed adf57ecc on 2.x
-
ambient.impact →
committed 36b59a44 on 2.x
Issue #3414538: Mostly working additive JS aggregation.
-
ambient.impact →
committed 36b59a44 on 2.x
-
ambient.impact →
committed 8483884d on 2.x
Issue #3414538: Remove __Host- prefix from page state cookie for now.
-
ambient.impact →
committed 8483884d on 2.x
-
ambient.impact →
committed 8098adf2 on 2.x
Issue #3414538: Set our own and Turbo JS to preprocess: false for now.
-
ambient.impact →
committed 8098adf2 on 2.x
-
ambient.impact →
committed 98e7736c on 2.x
Issue #3414538: First attempt at additive JS aggregation; not working.
-
ambient.impact →
committed 98e7736c on 2.x