There are currently no guidelines on MediaWiki.org around how to load JS on the page.
I had a useful conversation with Timo today but would love to see this documented.
```
<>>! @Jdlrobson wrote:
> Are there any performance guidelines on wiki which capture best practices of how to load JS code? e.g. something like the loading strategies section on https://phabricator.wikimedia.org/T235712 ?
<•Krinkle> Timo Tijhof Jdlrobson: It's generally either addModules on page load,
or mw.loader.using() to lazy load upon user interaction.[11:28 AM] @Krinkle wrote:
Jdlrobson: It's generally either addModules on page load, There's no other strategies afaik needed currently.
11:28 AM these two are documeted at https://www.mediawiki.org/wiki/ResourceLoader/Developing_with_ResourceLoader#Loading_modules
11:29 AM How to detect MobileFrontend is imho out of scope for RLor mw.loader.using() to lazy load upon user interaction. That's part of core conventions for ExtensionRegistry (in PHP) and based on what promises/public stable interfaces MF wants to expose/maintain client-side.
11:29 AM Any kind of conditional is fine imho.
11:30 AM <Jdlrobson> Jon Robson Krinkle: not detection of MFere's no other strategies afaik needed currently.
11:30 AM I was more interested in guidelines around WHEN to use mw.lthese two are documeted at https://www.mediawiki.org/wiki/ResourceLoader/Developing_with_ResourceLoader.using#Loading_modules
11:30 AM For instance on Echo we load WHEN we CLICK the button not on page loadHow to detect MobileFrontend is imho out of scope for RL. That's part of core conventions for ExtensionRegistry (in PHP) and based on what promises/public stable interfaces MF wants to expose/maintain client-side.
11:31 AM We are having aAny kind of conversadition now about how to architecture JS code in Vector so such a page would be super usefulal is fine imho.
>>! [11:30 AM] @Jdlrobson wrote:
> Krinkle: not detection of MF
11:31 AM <Jdlrobson> Jon Robson ULS loads all its code on page load unlike Echo. Guidelines would help us migrate that to better loading strategies.> I was more interested in guidelines around WHEN to use mw.loader.using
11:31 AM or mayb> For instance on Echo we loading all code upfront is the guideline? WHEN we CLICK the button not on page load
11:32 AM There is also talk about Vue.js - if we build out a new search interface with it, would we load the library up front or when the user focuses the search input?> We are having a conversation now about how to architecture JS code in Vector so such a page would be super useful
11:32 AM Again a guidelines page with a performance team seal of approval> ULS loads all its code on page load unlike Echo. Guidelines would help steer this conversation greatlyus migrate that to better loading strategies.
11:33 AM <•Krinkle> Timo Tijhof Right, that's less about how to implement a certain direction, but what direction to pick overall.> or maybe loading all code upfront is the guideline?
11:33 AM When something is needed on page load, it's addModules(). There's only one way to do that really, and that's documented. To lazy-load> There is also talk about Vue.js - if we build out a new search interface with it, you use mw.loader.using().would we load the library up front or when the user focuses the search input?
11:34 AM I don't see how it ties in with desktop/mobile target stuff.> Again a guidelines page with a performance team seal of approval would help steer this conversation greatly.
[11:33 AM] @Krinkle wrote:
Right, that's less about how to implement a certain direction, Why are we looking to change how existing code is loaded as part of that?but what direction to pick overall.
11:35 AM I agree we can use better docs around that,When something is needed on page load, it's addModules(). and will try to find it and/or write it.There's only one way to do that really, In general,and that's documented. later is better.To lazy-load, And loading Vue.js on page you use mw.load is imho a no-go no matter whater.using().
11:35 AM requestIdleCallback was a one-off experiment for Popups and shuld be removed,I don't see how it ties in with desktop/mobile target stuff. not recommended for any circumstance.Why are we looking to change how existing code is loaded as part of that?
11:36 AM (There's a task about that)I agree we can use better docs around that, and will try to find it and/or write it. In general, later is better. And loading Vue.js on page load is imho a no-go no matter what.
11:48 AM <Jdlrobson> Jon Robson Is it okay for me to write a task requesting such docs?requestIdleCallback was a one-off experiment for Popups and shuld be removed, not recommended for any circumstance.
11:48 AM Knowing performance guidelines on this would be useful.(There's a task about that)
>>! Vue.js being loaded on page load as already been mentioned several times.[11:48 AM] @Jdlrobson wrote:
> Is it okay for me to write a task requesting such docs?
11:49 AM Sorry for confusing by mentioning the targets system> Knowing performance guidelines on this would be useful. Vue.js being loaded on page load as already been mentioned several times.
11:49 AM My reason for mentioning that was a lot of the blockers for enabling mobile target on modules is making sure they load where they are needed rather than unconditionally> Sorry for confusing by mentioning the targets system.
11:49 AM A lot of extensions call addModules in OutputPage hook for example with no conditionals.> My reason for mentioning that was a lot of the blockers for enabling mobile target on modules is making sure they load where they are needed rather than unconditionally
11:50 AM I suspect guidelines around what's expected would help that initiative too by making it crystal clear even though hopefully spelling out the obvious> A lot of extensions call addModules in OutputPage hook for example with no conditionals.
Krinkle> Timo Tijhof
Yeah, I'll see what I can do, but ultimately it comes down to budgetting and performance review per-feature. I don't think we can describe clearly when it is fine to load on the page and when it isn't. In general, nothing should load on the page, unless it has to do something on that page and that it has to do it immediately when the page loads. That in itself is generally already something that should be avoided as it will not arrive
11:55 AM for all users (on slow devices they can comfortably read a paragraph and move on to another page before it arrives), so whenever possible first try pure CSS-only etc. But if it has to be client-side, and has to be on page load, and doesn't result in bad UX, then loading the minimum needed on the pages right away is probably fine, but that still depends on where we are in our budget and how computationally expensive the code is,> I suspect guidelines around what's expected would help that initiative too by making it crystal clear even though hopefully spelling out the obvious
and how[11:55 AM] @Krinkle wrote:
11:55 AMYeah, I'll see what I can do, but ultimately it comes down to budgetting and performance review per-feature. I don't think we can describe clearly when it is fine to load on the page and when it isn't. In general, nothing should load on the page, unless it has to do something on that page and that it has to do it immediately when the page loads. That in itself is generally already something that should be avoided as it will not arrive for all users (on slow devices they can comfortably read a paragraph and move on to another page before it arrives), so whenever possible first try pure CSS-only etc. But if it has to be client-side, and has to be on page load, and doesn't result in bad UX, then loading the minimum needed on the pages right away is probably fine, but that still depends on where we are in our budget and how computationally expensive the code is, and how large it is.
11:55 AM (Feel free to ignore this, I'm just drafting out loud)
11:59 AM Things that fall under this is: "init" code that adds event handlers to the Edit button click event, to the Search input focus event. Code that makes the reserved space for sortable icons in tables filled in with an actual button and makes those buttons work. (Slight contradiction, why is it okay to not lazy-load jquery.tablesorter? This is a trade-off in size of the code, overhead of having yet another init module, and latency when the
11:59 AM user clicks it given there is nothing to hide that latency behind, it is just sorting. Whereas search and edit do more things behind the scenes that already involve the network, so loading the code async is fine there. This is why the "init" code of VE isn't just a click handler, it also includes very minimal CSS to make that click result in the page looking like it is "loading".
12:01 PM also, I have a proposal to kill all "init" modules in favour of a standard attribute that will do this for you. E.g. you have an attribute in the HTML, when that is clicked, it will add a class that allows your CSS to make it look like however it should look when it is loading, and then when the code arrives it will call a certain method. The logic for this would be generic and only written once. See more at
12:01 PM https://phabricator.wikimedia.org/T183720
12:01 PM This would mean we can remove almost all JS from page load,also, I have a proposal to kill all "init" modules in favour of a standard attribute that will do this for you. E.g. you have an attribute in the HTML, when that is clicked, it will add a class that allows your CSS to make it look like however it should look when it is loading, and then when the code arrives it will call a certain method. except for stuff that does non-user facing things (like navtiming metrics),The logic for this would be generic and only written once. and init code for which the loading state is very complex (more than a simple class name switch can do).See more at https://phabricator.wikimedia.org/T183720
12:04 PM also, this will encourage use of "delegate event handlers". right now, a very common pattern (albeit a bad one) is to load JS that waits for dom-ready and then selects all of something and calls on(). This is problematic for many reasons. 1) It's poor UX because it means that when the JS has arrived, and most of the page is there and painted, the JS just sits there idle and the user can't click stuff. It waits for the whole page to be
12:04 PM there below the fold, until 2) it selects all the relevent elements which is expensive and slow, and 3) allocates many event handlers, again expensive. Whereas if we use a delegate handler like $(document.body).on('click', '.my-stuff') you can run that right away without waiting for dom-ready, and allocates only 1 event handler, and any elements that exist now or in the future that match will just workThis would mean we can remove almost all JS from page load, because we check it at
12:04 PM click-timeexcept for stuff that does non-user facing things (like navtiming metrics), instead of at select-timeand init code for which the loading state is very complex (more than a simple class name switch can do).
12:04 PM If I recall correctlyalso, this will encourage use of "delegate event handlers". right now, a very common pattern (albeit a bad one) is to load JS that waits for dom-ready and then selects all of something and calls on(). This is problematic for many reasons. 1) It's poor UX because it means that when the JS has arrived, and most of the page is there and painted, the JS just sits there idle and the user can't click stuff. It waits for the whole page to be there below the fold, until 2) it selects all the relevent elements which is expensive and slow, and 3) allocates many event handlers, again expensive. Whereas if we use a delegate handler like $(document.body).on('click', '.my-stuff') you can run that right away without waiting for dom-ready, and allocates only 1 event handler, and any elements that exist now or in the future that match will just work, because we check it at click-time, we adopted this in a few places last year around the Cite instrumentation that reading was involved withinstead of at select-time.
```If I recall correctly, we adopted this in a few places last year around the Cite instrumentation that reading was involved with.