From 0afecbaf07e6b540f3c09ffa83ddd9030ba3ec07 Mon Sep 17 00:00:00 2001 From: Ori Livneh Date: Mon, 7 Oct 2013 23:08:54 -0700 Subject: [PATCH] Add mediawiki.inspect module This patch adds a mediawiki.inspect ResourceLoader module. The module contains tools for inspecting page composition and performance. It is currently restricted to a set of static methods for querying the ResourceLoader module registry, the most useful of which is #inspectLoadedModules, which prints a list of loaded ResourceLoader modules and their size in kilobytes, ordered from largest to smallest. This method has a lazy-loading alias: mw.loader.inspect. Change-Id: I5a007fdf11196664f425cd7800eec7fc3fdb629f --- maintenance/jsduck/categories.json | 1 + maintenance/jsduck/config.json | 1 + resources/Resources.php | 4 + resources/mediawiki/mediawiki.inspect.js | 102 +++++++++++++++++++++++ resources/mediawiki/mediawiki.js | 11 +++ 5 files changed, 119 insertions(+) create mode 100644 resources/mediawiki/mediawiki.inspect.js diff --git a/maintenance/jsduck/categories.json b/maintenance/jsduck/categories.json index 962b0820c8..e98e9c0fbe 100644 --- a/maintenance/jsduck/categories.json +++ b/maintenance/jsduck/categories.json @@ -20,6 +20,7 @@ "name": "General", "classes": [ "mw.Title", + "mw.inspect", "mw.notification", "mw.user", "mw.util", diff --git a/maintenance/jsduck/config.json b/maintenance/jsduck/config.json index 5cce68d962..12458eeb00 100644 --- a/maintenance/jsduck/config.json +++ b/maintenance/jsduck/config.json @@ -13,6 +13,7 @@ "../../resources/mediawiki/mediawiki.log.js", "../../resources/mediawiki/mediawiki.util.js", "../../resources/mediawiki/mediawiki.Title.js", + "../../resources/mediawiki/mediawiki.inspect.js", "../../resources/mediawiki/mediawiki.notify.js", "../../resources/mediawiki/mediawiki.notification.js", "../../resources/mediawiki/mediawiki.user.js", diff --git a/resources/Resources.php b/resources/Resources.php index 880726b214..050e933f1b 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -646,6 +646,10 @@ return array( // must be loaded on the bottom 'position' => 'bottom', ), + 'mediawiki.inspect' => array( + 'scripts' => 'resources/mediawiki/mediawiki.inspect.js', + 'dependencies' => 'jquery.byteLength', + ), 'mediawiki.feedback' => array( 'scripts' => 'resources/mediawiki/mediawiki.feedback.js', 'styles' => 'resources/mediawiki/mediawiki.feedback.css', diff --git a/resources/mediawiki/mediawiki.inspect.js b/resources/mediawiki/mediawiki.inspect.js new file mode 100644 index 0000000000..c4766ffb4d --- /dev/null +++ b/resources/mediawiki/mediawiki.inspect.js @@ -0,0 +1,102 @@ +/*! + * Tools for inspecting page composition and performance. + * + * @author Ori Livneh + * @since 1.22 + */ +( function ( mw, $ ) { + + /** + * @class mw.inspect + * @singleton + */ + var inspect = { + + /** + * Calculate the byte size of a ResourceLoader module. + * + * @param {string} moduleName The name of the module + * @return {number|null} Module size in bytes or null + */ + getModuleSize: function ( moduleName ) { + var module = mw.loader.moduleRegistry[ moduleName ], + payload = 0; + + if ( mw.loader.getState( moduleName ) !== 'ready' ) { + return null; + } + + if ( !module.style && !module.script ) { + return null; + } + + // Tally CSS + if ( module.style && $.isArray( module.style.css ) ) { + $.each( module.style.css, function ( i, stylesheet ) { + payload += $.byteLength( stylesheet ); + } ); + } + + // Tally JavaScript + if ( $.isFunction( module.script ) ) { + payload += $.byteLength( module.script.toString() ); + } + + return payload; + }, + + /** + * Get a list of all loaded ResourceLoader modules. + * + * @return {Array} List of module names + */ + getLoadedModules: function () { + return $.grep( mw.loader.getModuleNames(), function ( module ) { + return mw.loader.getState( module ) === 'ready'; + } ); + }, + + /** + * Print a breakdown of all loaded modules and their size in kilobytes + * to the debug console. Modules are ordered from largest to smallest. + */ + inspectModules: function () { + var console = window.console; + + $( function () { + // Map each module to a descriptor object. + var modules = $.map( inspect.getLoadedModules(), function ( module ) { + return { + name: module, + size: inspect.getModuleSize( module ) + }; + } ); + + // Sort module descriptors by size, largest first. + modules.sort( function ( a, b ) { + return b.size - a.size; + } ); + + // Convert size to human-readable string. + $.each( modules, function ( i, module ) { + module.size = module.size > 1024 ? + ( module.size / 1024 ).toFixed( 2 ) + ' KB' : + ( module.size !== null ? module.size + ' B' : null ); + } ); + + if ( console ) { + if ( console.table ) { + console.table( modules ); + } else { + $.each( modules, function ( i, module ) { + console.log( [ module.name, module.size ].join( '\t' ) ); + } ); + } + } + } ); + } + }; + + mw.inspect = inspect; + +}( mediaWiki, jQuery ) ); diff --git a/resources/mediawiki/mediawiki.js b/resources/mediawiki/mediawiki.js index 39093e3e6a..4138ac8d97 100644 --- a/resources/mediawiki/mediawiki.js +++ b/resources/mediawiki/mediawiki.js @@ -1699,7 +1699,18 @@ var mw = ( function ( $, undefined ) { */ go: function () { mw.loader.load( 'mediawiki.user' ); + }, + + /** + * @inheritdoc mw.inspect#inspectModules + * @method + */ + inspect: function () { + mw.loader.using( 'mediawiki.inspect', function () { + mw.inspect.inspectModules(); + } ); } + }; }() ), -- 2.20.1