wiki.techinc.nl/includes/resourceloader/ResourceLoaderUserOptionsModule.php
Timo Tijhof 6f061f4db2 resourceloader: Bundle user.defaults as part of mediawiki.base
== Background ==

The `user.options` module is private, and thus has to be embedded in
the page HTML. This data is quite large. For example, on enwiki the
finalized mw.user.options object is about 3KB serialized/compressed
(7KB uncompressed).

The `user.defaults` module is an implementation detail of
`user.options`, and was created to accomplish mainly two things:

* Save significant data transfers by allowing it to be cached
  client-side without being part of the article.
* Ensure consistency between articles and allow faster deployment of
  changes, by not being part of the cacheable article HTML.

All our pageviews already load `user.defaults`, as a dependency of
the popular `mediawiki.api` and `mediawiki.user` modules. These are
used by `mediawiki.page.ready` (queued on all pages), and on Wikipedia
these are also loaded on all pages by ULS, VisualEditor, EventLogging,
and more.

As such, in practice, bundling "user.defaults" with "mediawiki.base"
will not cause the data to be loaded more often than before.

== What ==

* Add virtual "user.json" package file with the same data that
  was previously exported by ResourceLoaderUserDefaultsModule,
  and pass it to mw.user.options.set() from base module's entry point.

  An alternative way would be to use a "user.js" file, which would
  return a generated "mw.user.options.set()" expression. I went
  for exporting it as JSON for improved maintainability (reducing
  the amount of JS code written in PHP), and because it performs
  slightly better. The JS file would implicitly come with a file
  closure (tiny bit more bytes), and would then be lazy executed
  (tiny bit more time).

  The chosen approach allows the browser to compile the JSON
  off-the-main-thread ahead of time while the module response downloads.
  Then when the module executes, we can reference the JSON object
  and use it directly.

* Update internal dependency from `user.options`.

* Remove `user.defaults` module without deprecation. It is an internal
  module with no direct use anywhere in Git (Codeseach), and no use
  anywhere on-wiki (Global Search).

Change-Id: Id3916f94f75078808951863dea2b3a9c71b0e30c
2021-11-18 04:41:09 +00:00

84 lines
2.5 KiB
PHP

<?php
use MediaWiki\MediaWikiServices;
use MediaWiki\User\UserOptionsLookup;
/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
* @author Trevor Parscal
* @author Roan Kattouw
*/
/**
* Module for per-user private data that is transmitted on all HTML web responses.
*
* This module is embedded by ResourceLoaderClientHtml and sent to the browser
* by OutputPage as part of the HTML `<head>`.
*
* @ingroup ResourceLoader
* @internal
*/
class ResourceLoaderUserOptionsModule extends ResourceLoaderModule {
protected $origin = self::ORIGIN_CORE_INDIVIDUAL;
protected $targets = [ 'desktop', 'mobile' ];
/**
* @param ResourceLoaderContext $context
* @return string JavaScript code
*/
public function getScript( ResourceLoaderContext $context ) {
$user = $context->getUserObj();
$tokens = [
// Replacement is tricky - T287542
'patrolToken' => $user->getEditToken( 'patrol' ),
'watchToken' => $user->getEditToken( 'watch' ),
'csrfToken' => $user->getEditToken(),
];
$script = 'mw.user.tokens.set(' . $context->encodeJson( $tokens ) . ');';
$userOptionsLookup = MediaWikiServices::getInstance()->getUserOptionsLookup();
// Optimisation: Exclude the defaults, which we load separately and allow the browser
// to cache across page views. The defaults are loaded before this code executes,
// as part of the "mediawiki.base" module.
$options = $userOptionsLookup->getOptions( $user, UserOptionsLookup::EXCLUDE_DEFAULTS );
// Optimisation: Only output this function call if the user has non-default settings.
if ( $options ) {
$script .= 'mw.user.options.set(' . $context->encodeJson( $options ) . ');';
}
return $script;
}
/**
* @return bool
*/
public function supportsURLLoading() {
return false;
}
/**
* @return string
*/
public function getGroup() {
return 'private';
}
}