This task tracks actionables that came out of the ResourceLoader 2018 Review between @Catrope and myself.
Internal document: [Google Drive - ResourceLoader 2018 Review](https://docs.google.com/document/d/1SESOADAH9phJTeLo4lqipAjYUMaLpGsQTAUqdgyZb4U/edit#).
## Objective
(NOTE) Improve "time to interactive" and `mediaWikiLoadEnd` metric, by reducing the number of serial requests from 3 to 2.
## Current state
//(Sizes based on measures from en.wikipedia.org, desktop.)//
##### Req 1: Startup module
Current size: 29 KB (network transfer) - 85 KB (uncompressed).
* Defines mwNow, mwPerformance, isCompatible.
* Fetches "Base modules request" (Req 2).
* Once completed:
** Registers sources, modules, and site config.
** Process RLQ, which will initiate fetch for "Page modules request" (Req 3).
##### Req 2: Base modules
Current size: 49 KB (network transfer) - 178 KB (uncompressed).
* "jquery" (41 KB).
* "mediawiki" (8 KB).
* "wikibits" (0.4 KB).
## Problem
The startup module should be able to, on its own, start to handle `mw.loader.load()` calls from the page HTML, instead of having to make a second request first and waiting for that to come back.
## Plan
>>! **In a nut shell**:
>
> 1. Make the "mediawiki.loader" client simple and small enough to simply include in the "startup" module.
> 2. Load "jquery" and "wikibits" as a default-dependency implied for all regular modules.
The mediawiki.loader is already quite simple in terms of JavaScript logic. This is good because that means it won't be a problem to be compatible with the restrictions put on code in the startup module, namely that its //syntax// has to parse without errors in older browsers. Older browsers will never execute it, so usage of ES5 or ES6 methods is fine at run-time, but syntax-wise an older browser needs to be able to download and parse it, after which it essentially runs `!isCompatible()` and then returns gracefully.
The other requirement is for "mediawiki.loader" to not depend on jQuery. This is mostly done already, but there's a couple of call sites left that we have to migrate.
Once done, "jquery" can become a regular module that is loaded as dependency (in Req 3), thus eliminating Req 2.
For regular modules to be able to continue to assume jQuery, we need to re-introduce a concept of "default dependencies". And we should do it differently than what we did back in 2015 ("Default modules: mediawiki.user, mediawiki.util"), which (in retrospect) was implemented rather poorly (with a separate web request, using the synchronous top-queue).
High-level steps:
* Update "mediawiki.js" to not use jQuery.
* Split up between "mediawiki.loader" and "mediawiki.base".
* Implement "default dependencies" in "mediawiki.loader".
* In Startup module, replace "Base modules" request with embedding of "mediawiki.loader", and add "jquery, mediawiki.base, wikibits" as first entries in the "default dependencies".
## Sub tasks
startup.js:
* {icon check} Remove `mwLoadStart` and `mwPerformance`. – T160315 / <https://gerrit.wikimedia.org/r/427936>
* {icon check} Remove `mediaWikiLoadStart`. – T160315.
* {icon check} Move internal stub for `mwNow` back to mediawiki.js as the `mw.now` definition.
wikibits.js:
* Remove the obsolete document.write/writeln stubs. – ~~<https://gerrit.wikimedia.org/r/428041>~~
** Tried and reverted. Revisit later – T193314.
mediawiki.js (to become "mediawiki.loader"):
* mediawiki.errorLogger.js: Fine as-is (small, dependency-free, es3-compat).
* mediawiki.requestIdleCallback.js: Fine as-is (small, dependency-free, es3-compat).
* {icon check} mw.Map: Keep (used for mw.config). But remove use of isPlainObject(). Decide to either use all own keys regardless of type, or just all keys plainly.
* [ ] Message class: Not used by loader, and depends on mediawiki.html and mw.format Move to base.
* [ ] mw.message: Not used by loader, move to base.
* [ ] mw.msg: Not used by loader, move to base.
* mw.messages: Keep (mw.Map-based registry for loaded messages).
* mw.log: Keep (used by loader).
* [ ] mw.format: Move to base. Has one call in loader, but trivial to avoid.
* {icon check} mediawiki.track: Move to base. (Depends heavily on special features of $.Callbacks) Maybe leave a stub in mw.loader for track(), given it's used for error reporting.
* mw.loader:
** {icon check} addEmbeddedCSS: Fix to use plain array instead of $.Callback.
** {icon check} getMarker: We can remove this in favour of simply append to head if absent. – <https://gerrit.wikimedia.org/r/429124>
** {icon check} register: Remove or deprecate "dependencies as a function" feature. – <https://gerrit.wikimedia.org/r/428406>
** {icon check} addScript: Replace $.ajax with plain script.onload/onerror and callback. Promise only used in one place, with ".always()".
** {icon check} queueModuleScript: Replace overkill $.Deferred with simple callback parameter.
** {icon check} addLink: Use plain append/insert instead of jQuery.
** [ ] checkCssHandles: Find a way to change `mw.loader.using( ['site'] )` to a job so that it we won't need using() and $.Deferred.
** {icon check} doRequest: Inline simple version of `$.param()`.
** {icon check} asyncEval: Uses `$.globalEval()` (easy to replace for our current browsers, per jQuery 3).
** {icon check} execute: Idem, uses `$.globalEval()`.
** [ ] execute: Fix $ reference to be window.$ to avoid ref-error when RL loads jQuery itself.
** [ ] using: Depends on $.Deferred(), not used in loader, move to base. – (Blocked on: Internal callers)
* {icon check} mw.inspect(): Not used by loader. Move to base.
* [ ] mw.html: Not used by loader, move to base.
* [ ] mw.hook: Not needed, move to base.
* [ ] `$j` alias: Move to a one-line file in the "jquery" module (like for jquery-migrate). – (Blocked on swapping load order, because defining `$j` depends on having `mw.log.deprecate`.)
* {icon check} `mwLoadEnd`: Depends heavily on `mw.loader.using()`, and jQuery for when(), Deferred(), and more... Not needed here though, can be moved to the navtiming extension. – https://gerrit.wikimedia.org/r/#/c/434618/
Other stuff:
* {icon check} Simplify mediawiki.log.js
* Reduce size of startup module:
** [ ] Reduce amount of mw.config.set bloat in startup module from TMH. – T60082
** [ ] Reduce number of MobileFrontend modules. – T194098
** {icon check} Combine misc `mediawiki.special.*` modules. – <https://gerrit.wikimedia.org/r/432706>, [r/432707](https://gerrit.wikimedia.org/r/432707) (Outcome: Removed 8 modules)
** {icon check} Reduce number of UploadWizard modules. – @matmarex <https://gerrit.wikimedia.org/r/433888> (Outcome: Removed 31/37 modules)
** {icon clock-o} Reduce number of mediawiki.api modules. <https://gerrit.wikimedia.org/r/434179> (Outcome: Deprecated 10 modules, to be removed in 1.33)
** {icon check} Removed jquery.farbtastic module. <https://gerrit.wikimedia.org/r/434735> (Outcome: Removed 1 module)
** [ ] ...
-------
###### Startup response size breakdown
By @Catrope and @Krinkle
>
> Network transfer: 29 K
> Uncompressed content-length: 85,299
>
> Breakdown:
> * mwPerf + mwNow + isCompatible + nojs/NORLQ handling + startUp.addSource: 1,195 bytes (1.4%)
> * startUp.register: 67,999 bytes (80%)
> ** `jquery.*`: !!3013 bytes!!
> ** `mediawiki.*`: !!8532 bytes!! (core modules) {icon exclamation-triangle}
> *** `mediawiki.widgets.*`: 1042 bytes
> ** `oojs*`: 1073 bytes
> ** `skins.*`: 344 bytes
> ** `schema.*`: 2464 bytes
> ** `ext.*`: 51,857 bytes (Extension modules)
> *** CentralNotice: 1125 bytes
> *** VE+Citoid: !!2912 bytes!!
> *** `mobile.*` + Minerva: !!3588 bytes!!
> *** Echo+Thanks: 862 bytes
> *** RelatedArticles+RevisionSlider+TwoColConflict: !!1786 bytes!!
> *** ULS: 912 bytes
> *** ContentTranslation (CX): !!6573 bytes!!
> *** Wikibase: !!14,007 bytes!! {icon exclamation-triangle}
> *** Gadgets: !!4956 bytes!!
> *** TMH/mwEmbed: 1426 bytes
> * startUp.config: 15,537 bytes (18%)
> * RLQ handling + addScript: 485 (0.6%)
>