Add mediawiki.inspect module
authorOri Livneh <ori@wikimedia.org>
Tue, 8 Oct 2013 06:08:54 +0000 (23:08 -0700)
committerTimo Tijhof <krinklemail@gmail.com>
Wed, 9 Oct 2013 21:55:31 +0000 (23:55 +0200)
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
maintenance/jsduck/config.json
resources/Resources.php
resources/mediawiki/mediawiki.inspect.js [new file with mode: 0644]
resources/mediawiki/mediawiki.js

index 962b082..e98e9c0 100644 (file)
@@ -20,6 +20,7 @@
                                "name": "General",
                                "classes": [
                                        "mw.Title",
+                                       "mw.inspect",
                                        "mw.notification",
                                        "mw.user",
                                        "mw.util",
index 5cce68d..12458ee 100644 (file)
@@ -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",
index 880726b..050e933 100644 (file)
@@ -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 (file)
index 0000000..c4766ff
--- /dev/null
@@ -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 ) );
index 39093e3..4138ac8 100644 (file)
@@ -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();
+                                       } );
                                }
+
                        };
                }() ),