Requests for comment/Isolate custom jQuery libraries

From mediawiki.org
Request for comment (RFC)
Isolate custom jQuery libraries
Component Frontend
Creation date
Author(s) Daniel Friesen
Document status implemented

MediaWiki's resources/jquery/ folder contains a incoherent mix of 3rd party libraries and custom libraries. We also appear to make no effort at all in retaining information on where 3rd party libraries are downloaded from or keeping them up to date (to find the origin of many of these I had to do a web search for the name and isolate the source among a number of similar libraries that showed up in search results).

As a result we're left with an unmaintainable mess. Every single real 3rd party jQuery based library we use is now out of date (some also unmaintained) or no longer of any value. Our list of jQuery plugins contains a number of poor quality 3rd party libraries many with better maintained alternatives. Many of our own custom "generic" libraries have no authorship or license data leaving them defaulting to GPL which makes them even less useful outside of MW. At a glance one cannot tell what code is custom. It's hard to know what files need to be maintained by us and which ones we should be avoiding modifications to. And as a result even our own code bitrots without proper maintenance – one of them even still uses the deprecated jQuery.bind.

Cleanup[edit]

This RFC recommends taking a number of actions to clean up our jQuery scripts:

  • 3rd party libraries and MediaWiki specific libraries should be isolated from each other:
    • resources/jquery/ should be restricted to 3rd party unmodified libraries.
    • Custom and forked jQuery libraries should go into another directory such as jquery.custom or jquery.local.
    • Libraries integrated directly with MediaWiki's mediaWiki.* or dependent on its environment should go in another directory such as mediawiki.jquery.
    • Update (21/04/2014): Gerrit change 123782 splits modules in /lib for 3rd party libraries and /src for mediawiki-maintained libraries.
  • 3rd party jQuery libraries should all be updated after being tested for compatibility.
  • If a generic custom library genuinely may have use to 3rd parties we should make an effort to move the script out of MW and maintain it in its own repo and site. Becoming a user of it and moving it to the 3rd party dir instead of maintaining it as part of MediaWiki.
  • We should consider attempting to integrate bower into our workflow.
    • Install 3rd party libraries where possible through bower. Potentially using grunt to copy the specific files we need to the resources folder only committing the stuff we use and maintaining a lightweight index of what we've extracted from bower.
    • Some form of monitoring should use the bower integration to warn us of when a library falls out of date.
  • Some 3rd party libraries should be audited.
    • Libraries like jquery.json and jquery.xmldom which have lost their use should be deprecated and removed.
    • Poorly or "un" maintained 3rd party libraries should be audited against similar 3rd party libraries.
      • "Can this 3rd party library be deprecated and replaced with one of the other more recently maintained libraries?"
      • Libraries which use a public source code repo should be preferred over those distributing, zip files, etc... on random websites. And libraries that support bower should be preferred the most (bower appears to have grown fairly large and most well-maintained JS libraries support it).
  • Forked libraries should be audited and have additional things required of them:
    • Locally forked libraries must explicitly declare what they have changed from the original library and why it is necessary.
    • Forked libraries with potentially dubious rationales for forking – ones which make the burden of keeping the library up to date compared to the original library greater than the use of the forked modifications – should be un-forked.
    • The forked library's should be checked against its origin and similar 3rd party libraries regularly. If it ever becomes possible to do the same thing without the need for a fork, the forked library should be deprecated, removed, and replaced with a maintained 3rd party library.

Extra[edit]

These aren't directly related to cleanup but came up while auditing the libraries we use:

  • We should avoid stuff that does JS animation and see if we can replace them with stuff that does CSS transitions/keyframes when possible.
    • jquery.cycle.all.js is a perfect case for this. It does JS animations with jQuery. It's pretty unknown compared to other sliders. And the only thing I can find that uses it is mediawiki/extension/UnitTest.git@ExtensionsSeleniumSlideshowTemplate.php. It's not even a core RL module, this extension blatantly includes it from core in a raw script tag. (Was this extension ever reviewed? Besides messing with core like this the Extension also defines a very generic "Debug" class and does require_once 'Debug.php'; without properly anchoring it much less autoloading it.)
    • There is also jquery.spinner.js which we could start using something like spin.js to do the actual spinner. Technically this module doesn't do any JavaScript animation however it uses a set of .gifs. And while gif animations don't defer to the JS engine every frame they do image re-draws for each frame and don't perform as well as a CSS animation using transformations which do absolutely no re-draws and allow the GPU to do most of the work.[1] Testing our watchlist .gif the difference between an animated .gif spinner and a css animated spinner like spin.js on a desktop alone is ~33FPS vs 55-60FPS.
  • jquery.client.js doesn't even use jQuery methods besides checking the body for an .rtl class. This should be moved to something like mw.client.
  • Many of the methods we add in jquery.mwExtension.js are theoretically covered by Underscore.js/Lo-Dash – which also provides a plethora of collection methods we're probably writing ugly code to work around lack of support for – and all the rest are covered by by Underscore.string.js. We should really deprecate all of mwExtension modifying code to use methods 3rd party libraries define.
  • Something to keep in mind in the future are EcmaScript 6 Promises . We use a tiny bit of thenables in the form of a few jQuery.Deferred()s. However if async code ever gets any more complex it would be a good idea to consider using the standard's Promises which are much more powerful than jQuery.Deferred and make promise-based code much cleaner. There is a wip change for this.

Libraries in resources/jquery/[edit]

Here's an audit of the contents of the resources/jquery/ library.

3rd party libraries[edit]

These are the real 3rd party libraries inside of resources/jquery/.

Local "generic" jQuery libraries[edit]

These libraries inside resources/jquery/ do not appear to exist outside of MediaWiki. They are either custom libraries written specifically for MediaWiki and never distributed elsewhere. Or local forks of 3rd party libraries.

  • jquery.arrowSteps.js – No 3rd party repo; GPL; Appears to only exist inside MediaWiki and was written by NeilK during the time the WMF employed him.
  • jquery.autoEllipsis.js – Cannot find 3rd party repo; Does not declare origin, author, or even license.
  • jquery.byteLength.js – Cannot find 3rd party repo; Original authors are MW contributors; Tied to jquery.byteLimit.js)
  • jquery.byteLimit.js – Cannot find 3rd party repo; Authors are MW contributors.
  • jquery.checkboxShiftClick.js – Cannot find 3rd party repo; GPL; Author is a MW contributor.
  • jquery.color.js – Forked MediaWiki specific repo; Looks pretty out of date compared to the original repo https://github.com/jquery/jquery-color/
  • jquery.colorUtil.js – No 3rd party repo (tied to the forked jquery.color.js)
  • jquery.delayedBind.js – Cannot find 3rd party repo; Does not declare origin, author, or even license. (If we used Underscore.js/Lo-Dash it looks like delayedBind could trivially be replaced by jQuery.fn.on+_.debounce. Daniel Friesen (Dantman) (talk) 13:32, 12 October 2013 (UTC))[reply]
  • jquery.expandableField.js – Cannot find 3rd party repo; Does not declare origin, author, or even license.
  • jquery.farbtastic.js – MediaWiki specific forked version of the old Farbtastic code which died, was forked, died again, and then was forked again.
  • jquery.footHovzer.js – Cannot find 3rd party repo; No explicit license; Author is a MW contributor.
  • jquery.getAttrs.js – Cannot find 3rd party repo; No explicit license; Author is a MW contributor.
  • jquery.hidpi.js – Cannot find 3rd party repo; Does not declare origin, author, or even license.
  • jquery.highlightText.js – Cannot find 3rd party repo; Does not declare origin, author, or even license.
  • jquery.placeholder.js – Cannot find 3rd party repo; MIT; Authors are MW contributors.
    bug 57179 advises merging with an external library of the same name. Matma Rex (talk) 13:55, 27 November 2013 (UTC)[reply]
  • jquery.qunit.completenessTest.js – Cannot find 3rd party repo; No explicit license; Author is a MW contributor.
  • jquery.suggestions.js – Cannot find 3rd party repo; Does not declare origin, author, or even license.
  • jquery.tabIndex.js – Cannot find 3rd party repo; Does not declare origin, author, or even license.
  • jquery.textSelection.js – Cannot find 3rd party repo; Does not declare origin, author, or even license.

MediaWiki Specific libraries[edit]

These libraries are directly dependent on the MediaWiki environment. Using things like MW specific or mw- prefixed classes.

  • jquery.mw-jump.js – Uses our .mw-jump class.
  • jquery.mwExtension.js – Doesn't use mediaWiki.* or our markup but is clearly a MW-specific file.
  • jquery.client.js – Cannot find 3rd party repo; Does not declare origin, author, or even license; Uses our body.rtl class.
    This was created during the UsabilityInitiative days, I think. It's entirely ours. Matma Rex (talk) 13:36, 27 November 2013 (UTC)[reply]
  • jquery.spinner.js – Cannot find 3rd party repo; Does not declare origin, author, or even license; Uses a mw-spinner class. (I recommend using something like spin.js over the gifs here. Daniel Friesen (Dantman) (talk) 13:32, 12 October 2013 (UTC))[reply]
    This was refactored from some random functions in wikibits.js, see bug 30499, and then made more useful. Entirely ours as well. Matma Rex (talk) 13:36, 27 November 2013 (UTC)[reply]

MediaWiki Integrated libraries[edit]

These are the worst of the bunch. These libraries directly use our mediaWiki.* APIs.

  • jquery.badge.js
  • jquery.localize.js
  • jquery.makeCollapsible.js
  • jquery.tablesorter.js

However, none of these really depend on running in MediaWiki context; the mediaWiki object seems to be used solely for localisation (mw.msg, mw.language.convertNumber) and logging (mw.log). tablesorter also uses mw.config to get some data which really should be in mw.language.

For example, reusing jquery.makeCollapsible only requires trivial changes to remove the usages [1], and it could be similarly trivially made to only use the mediaWiki object when it's available and fall back gracefully on English-only localisation, assuming we can agree on doing this.

I did not investigate the other libraries, but they are likely similarly easy to port. Maybe we should start distributing some of our libs separately, too. Matma Rex (talk) 13:17, 27 November 2013 (UTC)[reply]

References[edit]