This task tracks actionables that came out of the ResourceLoader 2018 Review between @Catrope and myself.
Objective
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
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:
- Refactor mediawiki.js to not require jQuery. (Sub tasks below)
- Split off the "mediawiki.base" module from "mediawiki".
- Remove "mediawiki" module from the base module's request, and instead embed it directly the startup module response.
- Implement "default dependencies" concept.
- In Startup module, remove "Base modules request", instead listing those modules as "default dependencies". Then, in startup.js simply call startUp(); directly at the end of the closure.
Sub tasks for "Refactor mediawiki.js to not require jQuery"
startup.js:
- Remove mwLoadStart and mwPerformance. – T160315 / https://gerrit.wikimedia.org/r/427936
- Remove mediaWikiLoadStart. – T160315.
- 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).
- 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.
- 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:
- addEmbeddedCSS: Fix to use plain array instead of $.Callback.
- getMarker: We can remove this in favour of simply append to head if absent. – https://gerrit.wikimedia.org/r/429124
- register: Remove or deprecate "dependencies as a function" feature. – https://gerrit.wikimedia.org/r/428406
- addScript: Replace $.ajax with plain script.onload/onerror and callback. Promise only used in one place, with ".always()".
- queueModuleScript: Replace overkill $.Deferred with simple callback parameter.
- 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.
- doRequest: Inline simple version of $.param().
- asyncEval: Uses $.globalEval() (easy to replace for our current browsers, per jQuery 3).
- 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)
- 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: Not needed, move to base.
- 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:
- Simplify mediawiki.log.js
Startup response size breakdown
Moved to T202154