Page MenuHomePhabricator

Add support for alternating versions of a module in ResourceLoader (e.g A/B testing or opt-in betas)
Closed, DeclinedPublic

Description

As more UI interaction moves to client-side JavaScript in the future, we have some nice opportunities to enhance ResourceLoader to make it easier to deliver alternate versions of particular modules.

This would be hugely useful for Gadget authors, who could create experimental versions of their gadgets for testing.

For core & extension modules, we could send alternate versions to people who have opted-in to beta-testing or general A/B testing groups.

For cacheability, the actual load.php requests should still contain all the necessary information to disambiguate what's being loaded, so possibly we'd need to export available versions to the JS side, so the loader can pick the appropriate variant to request.

No super rush on this, it'll need to be considered. :)


Version: 1.18.x
Severity: enhancement

Details

Reference
bz28910

Event Timeline

bzimport raised the priority of this task from to Medium.Nov 21 2014, 11:27 PM
bzimport set Reference to bz28910.
bzimport added a subscriber: Unknown Object (MLST).

The way this is currently possible:

  • Create the different versions as different modules
  • Register a startup module
  • Use mw.user.bucket() in the startup module, followed by a call to mw.loader.load depending on the bucketing.

I think the currently provided built-in methods for this are pretty good already nowadays:

  • Module dependencies
  • Extending/overwriting/overloading javascript object methods
  • mw.user.bucket() (randomly bucket users according to a provided ratio and uses a cookie to remain the session)
  • Extension:ClickTracking (if you it)
  • Dynamic dependencies by using a javascript function as a dependency (instead of an array)

Then:

  • Create the different versions as different modules (e.g. ext.fooBar.quux.v1, ext.fooBar.quux.v2; if needed they can depend on a general module that common logic, which is likely the case. You just extend it to implement the variation).
  • Register an "init" module (e.g. ext.foobar.quux.init)
  • Use mw.user.bucket() in the init module and call mw.loader.load to load the appropriate version.

If you want to save the additional http request, you could even go a step further and still have a common load.php cache:

  • Instead of the "init" module being an in-between module, it becomes the actual module itself. With the right version as its only dependency (no scripts, no styles, no messages).
  • Register the "init" module with a function as "dependencies" (in JavaScript) instead of an array. And have that return the correct modulename in an array.