Page MenuHomePhabricator

mw.loader.load for external script should not include the same twice
Closed, DeclinedPublic

Description

legacy importScript* had something like this. I think we should implement it in mw.loader.load as well.
(ie. keep an array of loaded urls by type, and check if inArray)


Version: 1.18.x
Severity: enhancement

Details

Reference
bz26814

Event Timeline

bzimport raised the priority of this task from to Medium.Nov 21 2014, 11:15 PM
bzimport set Reference to bz26814.

importScript does not pay attention to module names, which causes this issue. If you NEVER use importScript* to load something that is available through mediaWiki.loader.load then you will be fine.

I ran the following line from the console on a fresh logged out load of translatewiki.net (10 times):

mw.loader.load('http://toolserver.org/~krinkle/main.css', 'text/css')

10 <link> elements were appended to the <head>

With legacy importScript('Namespace:Title') this tracking object and "preventing doubles" was a easy solution for wikis to be loading scripts from multiple places and making sure libraries and common scripts are only loaded once (sort of a dependancy stack on top of scripts. They listed the depending scripts on top inside importScript()).

Such as: Many scripts/gadgets on Commons have importScript('MD5.js');

For wiki-pages this is useful, but for URLs this sometimes introduced bugs, such as:

  • Dynamic content from static urls (ie. polling the recentchanges API, later requests should not be ignored)
  • Synchronous/on-the-fly resources that are order dependant will function wrong if loaded (also) early.
  • CSS may cascade the wrong way (rare though, likely result of bad practices)

I suggest WONTFIXing this. The dependancy tree and prevention of double-loading will be taken care of by Gadgets.

Although there are a few ways to not including the same twice, here's an example for the MD5.js library.

  • It would be defined as a (hidden?) resource-loader gadget.
  • For other gadgets: Remove importScript('MD5.js') and add [dependancies:MD5] to the definition instead.
  • For user scripts: Replace importScript('MD5.js') with mw.loader.using( 'ext.gadget.MD5', MyScript.initFunction );

Per discussion during Hackathon in Berlin, marking as WONTFIX.

Whenever people use importScript's non-double loading as dependancy, should use gadgets and add those as dependancies.

Primary reason being that importScriptURL (and now mw.loader.load) is being used (as documented) to load javascript stuff with callbacks. Including but not limited to periodic requests (ie. polling the API). If we would filter out urls already loaded then that would end up really weird.

  • Bug 29001 has been marked as a duplicate of this bug. ***