mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/Vector.git
synced 2024-11-30 18:35:44 +00:00
8cf278d305
As part of comparing Vue search with legacy search, we need to track how long it takes to lazy load the wvui library. A similar metric was added to measuring the mediawiki.searchSuggest module in I0fa6b8904bd43c87a68e9161f00d686a0e588966. This commit adds the following metrics which will only be used in our synthetic tests. We are not doing RUM tests at this time. To test locally, add the following to your LocalSettings.php and append the query param `useskinversion=2` e.g. (http://localhost:8181/wiki/Test?useskinversion=2): ``` $wgVectorUseCoreSearch = false; ``` Marks: * mwVectorVueSearchLoadStart: Marks the start of loading the search module. * mwVectorVueSearchLoadEnd: Marks the end of loading the search module. Measures: * mwVectorVueSearchLoadStartToLoadEnd: Measures the time it takes to load the search module. Bug: T251544 Change-Id: I14e44b45a66213821d69cd22395fedbae747da88
172 lines
5.1 KiB
JavaScript
172 lines
5.1 KiB
JavaScript
/**
|
|
* Disabling this rule as it's only necessary for
|
|
* combining multiple class names and documenting the output.
|
|
* That doesn't happen in this file but the linter still throws an error.
|
|
* https://github.com/wikimedia/eslint-plugin-mediawiki/blob/master/docs/rules/class-doc.md
|
|
*/
|
|
/* eslint-disable mediawiki/class-doc */
|
|
|
|
/** @interface VectorResourceLoaderVirtualConfig */
|
|
/** @interface MediaWikiPageReadyModule */
|
|
|
|
var /** @type {VectorResourceLoaderVirtualConfig} */
|
|
config = require( /** @type {string} */ ( './config.json' ) ),
|
|
// T251544: Collect search performance metrics to compare Vue search with
|
|
// mediawiki.searchSuggest performance.
|
|
SHOULD_TEST_SEARCH = !!(
|
|
!config.wgVectorUseCoreSearch &&
|
|
window.performance &&
|
|
performance.mark &&
|
|
performance.measure &&
|
|
performance.getEntriesByName ),
|
|
LOAD_START_MARK = 'mwVectorVueSearchLoadStart',
|
|
LOAD_END_MARK = 'mwVectorVueSearchLoadEnd',
|
|
LOAD_MEASURE = 'mwVectorVueSearchLoadStartToLoadEnd',
|
|
SEARCH_FORM_ID = 'simpleSearch',
|
|
SEARCH_INPUT_ID = 'searchInput',
|
|
SEARCH_LOADING_CLASS = 'search-form__loader',
|
|
SEARCH_MODULE_NAME = config.wgVectorUseCoreSearch ?
|
|
'mediawiki.searchSuggest' :
|
|
'skins.vector.search';
|
|
|
|
/**
|
|
* Loads the search module via `mw.loader.using` on the element's
|
|
* focus event. Or, if the element is already focused, loads the
|
|
* search module immediately.
|
|
* After the search module is loaded, executes a function to remove
|
|
* the loading indicator.
|
|
*
|
|
* @param {HTMLElement} element search input.
|
|
* @param {string} moduleName resourceLoader module to load.
|
|
* @param {function(): void} afterLoadFn function to execute after search module loads.
|
|
*/
|
|
function loadSearchModule( element, moduleName, afterLoadFn ) {
|
|
|
|
function requestSearchModule() {
|
|
if ( SHOULD_TEST_SEARCH ) {
|
|
performance.mark( LOAD_START_MARK );
|
|
}
|
|
mw.loader.using( moduleName, afterLoadFn );
|
|
element.removeEventListener( 'focus', requestSearchModule );
|
|
}
|
|
|
|
if ( document.activeElement === element ) {
|
|
requestSearchModule();
|
|
} else {
|
|
element.addEventListener( 'focus', requestSearchModule );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Event callback that shows or hides the loading indicator based on the event type.
|
|
* The loading indicator states are:
|
|
* 1. Show on input event (while user is typing)
|
|
* 2. Hide on focusout event (when user removes focus from the input )
|
|
* 3. Show when input is focused, if it contains a query. (in case user re-focuses on input)
|
|
*
|
|
* @param {Event} event
|
|
*/
|
|
function renderSearchLoadingIndicator( event ) {
|
|
|
|
var form = /** @type {HTMLElement} */ ( event.currentTarget ),
|
|
input = /** @type {HTMLInputElement} */ ( event.target );
|
|
|
|
if (
|
|
!( event.currentTarget instanceof HTMLElement ) ||
|
|
!( event.target instanceof HTMLInputElement ) ||
|
|
!( input.id === SEARCH_INPUT_ID ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( !form.dataset.loadingMsg ) {
|
|
form.dataset.loadingMsg = mw.msg( 'vector-search-loader' );
|
|
}
|
|
|
|
if ( event.type === 'input' ) {
|
|
form.classList.add( SEARCH_LOADING_CLASS );
|
|
|
|
} else if ( event.type === 'focusout' ) {
|
|
form.classList.remove( SEARCH_LOADING_CLASS );
|
|
|
|
} else if ( event.type === 'focusin' && input.value.trim() ) {
|
|
form.classList.add( SEARCH_LOADING_CLASS );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Attaches or detaches the event listeners responsible for activating
|
|
* the loading indicator.
|
|
*
|
|
* @param {HTMLElement} element
|
|
* @param {boolean} attach
|
|
* @param {function(Event): void} eventCallback
|
|
*/
|
|
function setLoadingIndicatorListeners( element, attach, eventCallback ) {
|
|
|
|
/** @type { "addEventListener" | "removeEventListener" } */
|
|
var addOrRemoveListener = ( attach ? 'addEventListener' : 'removeEventListener' );
|
|
|
|
[ 'input', 'focusin', 'focusout' ].forEach( function ( eventType ) {
|
|
element[ addOrRemoveListener ]( eventType, eventCallback );
|
|
} );
|
|
|
|
if ( !attach ) {
|
|
element.classList.remove( SEARCH_LOADING_CLASS );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Marks when the lazy load has completed.
|
|
*/
|
|
function markLoadEnd() {
|
|
if ( SHOULD_TEST_SEARCH && performance.getEntriesByName( LOAD_START_MARK ).length ) {
|
|
performance.mark( LOAD_END_MARK );
|
|
performance.measure( LOAD_MEASURE, LOAD_START_MARK, LOAD_END_MARK );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize the loading of the search module as well as the loading indicator.
|
|
* Only initialize the loading indicator when not using the core search module.
|
|
*
|
|
* @param {Document} document
|
|
*/
|
|
function initSearchLoader( document ) {
|
|
var searchForm = document.getElementById( SEARCH_FORM_ID ),
|
|
searchInput = document.getElementById( SEARCH_INPUT_ID );
|
|
|
|
if ( !searchForm || !searchInput ) {
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* 1. If we're using the search module from MediaWiki Core (searchSuggest),
|
|
* load the module.
|
|
* 2. If we're using a different search module, enable the loading indicator
|
|
* before the search module loads.
|
|
**/
|
|
if ( config.wgVectorUseCoreSearch ) {
|
|
loadSearchModule( searchInput, SEARCH_MODULE_NAME, function () {} );
|
|
} else {
|
|
setLoadingIndicatorListeners( searchForm, true, renderSearchLoadingIndicator );
|
|
loadSearchModule(
|
|
searchInput,
|
|
SEARCH_MODULE_NAME,
|
|
function () {
|
|
markLoadEnd();
|
|
|
|
setLoadingIndicatorListeners(
|
|
/** @type {HTMLElement} */ ( searchForm ),
|
|
false,
|
|
renderSearchLoadingIndicator
|
|
);
|
|
}
|
|
);
|
|
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
initSearchLoader: initSearchLoader
|
|
};
|