Problem/Motivation
With JS aggregation enabled (at /admin/config/development/performance), we get the following error when clicking the "Tour" button:
DOMException: IntersectionObserver constructor: rootMargin must be specified in pixels or percent.
and the tour does NOT appear.
With JS aggregation enabled, everything works fine and as expected.
The "rootMargin" code can be found in tour.js:
...
_={rootMargin:-h+"px "+-m+"px "+-w+"px "+-y+"px"
...
Steps to reproduce
- Define a tour for the frontend and enable aggregation.
- See console for the error
Proposed resolution
Find out why this is broken with aggregation enabled
Remaining tasks
User interface changes
API changes
Data model changes
Comments
Comment #2
anybodyOkay I think I found the reason! The library definitin is wrong, it must point out that the code is already minified!
See https://www.drupal.org/docs/develop/creating-modules/adding-assets-css-j...
Comment #4
anybodyWe could also consider renaming tour.js to tour.min.js or for clarification, but of course that's totally optional.
Comment #5
anybodyWhile I'm 100% sure the current implementation is wrong and the fix is right, we're still seeing the same issue even after the fix.
We should nevertheless fix this and see if the issue can be reproduced before and after (manually). @smustgrave could you maybe give it a try?
Comment #6
smustgrave commentedWill merge but I'm not experiencing any issue.
Comment #8
anybodyThanks @smustgrave. Code-wise the fix is clearly correct, I'd say... so I guess we're running into this for further reasons. Some other modules like blazy also use IntersectionObserver and maybe conflict. Still the error clearly appears in Tour module as described with aggregation enabled. For that reason, I'll set this to NW again, after merge.
Comment #9
anybodyBesides fixing our possible conflict, it would be great to run the tests with and without aggregation enabled!
With the fix merged and the feedback from @smustrage, I'm setting the priority to normal here.
Comment #11
anybodyOkay tests are also green with aggregation enabled (if it works as expected in the tests).
Still, we might add a "WithAggregation" subclass of each test for the future using this setting? So tests should run with and without aggregation? Or does anyone know a better approach.
And I'll try to find the root cause for us.
Comment #12
anybodyFYI: The issue is still present with Shepherd.js 13.0.3 (Tour 2.0.13)
Comment #13
anybodyDebugging this I found out that the variables in our case are:
{ rootMargin: "-573px NaNpx NaNpx -15px", threshold: 1 }Comment #14
anybodyFinal results so far:
i.clientWidthand
i.clientHeightare
undefinedwith aggregation enabled andconst i = $(e);(jQuery) behaves differently.So maybe a "wrong" jQuery is used with aggregation or the asset order is wrong with aggregation or something like that... Crazy!
In #3540255: Race condition in _removeIrrelevantTourItems() e.g. with BigPipe if page is not yet fully loaded @smustgrave wrote:
Comment #15
anybody@smustgrave or do you think this might be caused by the
/core/themes/stable9/js/tour.jsoverrides we're seeing?Comment #16
smustgrave commentedNo clue, I'm not seeing this issue at all so hard for me to say.
Comment #17
anybodyThanks, we'll dig deeper... Might also be a conflict with another module. Back to #14 for us.
Comment #18
johnny5th commentedJust to throw some more info in: we ran into problems getting Splide and Tour working together on the same page (frontend pages). Note, the tour tips were not targeting anything in the Splide carousel.
As anonymous with JS agg turned off it worked fine. When logged in with Bigpipe, activating Tour broke the page with a partial tour render.
Splide has an option to load the library globally, which seemed to fix the problem, till I turned JS agg on, and then it totally broke JS on the page.
Comment #20
smustgrave commentedDon't know if this fixes it but added big_pip to the javascript tests and it passes
Comment #22
anybodyThanks @smustgrave sadly the reordering doesn't fix it. But we just found out that
preprocess: falsefixes the issue. As long as dist/tour.js is not part of an aggregated js file, it's fine!Possible causes:
I could imagine that this is a combination of different things:
1. "weight" property: I don't know why
weight: -1is used, but it would be great to tell why (and add a comment for the future). If it's not needed, it should be removed. Maybe it just runs to early as part of the Drupal aggregate?2. The
build/tour.jscompiled source pollutes the global scope with a lot of functions. Aggregated with other JS in the same JS file, that may conflict if any other module minifies to the same variable names!The code looks like this:
Possible solutions:
1. Use the
preprocess: falsequickfix from the MR. I'd even vote to merge it, until we clearly know how this happens and how to fix it. The impact should be minimal, but it removes the side-effects. Maybe what we see is even a side-effect of #3416508: Skip generating aggregates that won't be used for stale asset requests but I don't think so.2. Do not pre-built the sources and do not aggregate tour.js with the library in
dist. Imho that is not Drupal best-practice and may lead to such side-effects. Instead use the libraries functionality from Drupal for local sources or CDN: https://docs.shepherdjs.dev/guides/install - if the maintainer agrees, let's do that in a separate issue. There are further benefits, for example the user can independently upgrade to a (paid if commercial) Shepherd v14. As long as the modules tour.js is bundled, that seems impossible. Furthermore we won't need the untypical build step anymore.Instead asset-packagist or a simple download into libraries folder or CDN should be used, like in most other contrib modules.
Short-term I'd vote for (1) and long-term for (2)! :)
Comment #23
anybodyFix attached as static patch until this is finally solved :)
Comment #24
thomas.frobieterI can confirm the preprocess: false fix works! Thanks!! +1 for the suggestions.
Comment #25
anybodyComment #26
johnny5th commentedThis worked for me! Thank you!
Comment #27
smustgrave commentedNot 100% against redoing how the library is compiled but like what we came up with in #3480031: Update shepherd.js library and how we currently compile the asset personally.
I can't remember but there were reasons we did it this way vs just having a copy of the shepherd like before. I think it was because it was an mjs file and just wasn't loading or working with the tour.js file.
Comment #28
anybodyThanks @smustgrave what do you think, should we merge the workaround for the meantime and open a separate issue to check the library separation? Before that we should definitely check the reasons it was done this way in #3480031: Update shepherd.js library!
Comment #29
smustgrave commentedcan we remove the todo and I'll merge.
Comment #30
smustgrave commentedAnd unless it becomes a major problem not sure we need to break up how it’s compiled. I’m 90% positive moving to it’s own library and loading like it did in core no longer works with v13 of shepherd. Core was using v10
Comment #31
smustgrave commentedAnd the weight was added because in 11.1 asset ordering was changed and tour completely stopped working because it was loading last
Comment #32
anybodyMhm but shouldn't we better keep it, as it shouldn't be there forever, due to its workaround nature?
Should we give it a try in a separate issue and see if it works? Shouldn't be too hard, I guess?
MIGHT be that this could also be resolved in the separation issue, if the reason is the library bundling?
In #3480031: Update shepherd.js library @darvanen wrote:
When using it from CDN or library, having the library as dependency of the tour initialization should happen like for any other JS?
Comment #33
grevil commentedIf you're not totally against it, @smustgrave, I'd create an issue to give the regular separation a try and we can simply check the results in a MR?
Comment #36
smustgrave commentedSo can we still remove the todo, adding that I don't see as a workaround it's perfectly valid.
And know it doesn't cover the scenario here but can we add big_pip to tests/src/FunctionalJavascript/TourJavascriptTest.php
Comment #37
anybodyThanks, I removed the @todo!
Regarding BigPipe: Yes and the other part would be a test with and without aggregation. With the fix it should be green, without not... Do you have any ideas regarding that? (#9 )
Still I'm fine to leave that out, at least for now with the fix, just saying because BigPipe addition is similar...
Comment #38
smustgrave commentedMaybe we could transform the same test to do a loop just twice?
Comment #39
smustgrave commentedPushed a change, know it doesn't cover the scenario here but closest we may be able?
Comment #40
anybodyNice @smustgrave! Maybe add a comment why we're doing that? I don't think it's self-explaining.
I'm fine with that, while it probably won't hit 100% ...
Comment #42
smustgrave commentedStill have an issue or 2 in flight but will do a release after those.