From d6603a7302282d053226633b26b104758092289f Mon Sep 17 00:00:00 2001 From: Leshana Date: Sat, 6 Jun 2020 01:36:36 -0400 Subject: [PATCH] Combine all nanoui templates into a single resource bundle. This reduces the number of assets needing to be sent on join by 150ish. - Nanoui scripts modified to load templates in parallel instead of one at a time. - Nanoui scripts modified to be willing to load from the resource bundle if available, falling back to ajax-loading the individual templates if absent. --- code/modules/client/asset_cache.dm | 23 +++++---- code/modules/nano/nanoui.dm | 1 + nano/js/nano_template.js | 79 ++++++++++++------------------ 3 files changed, 46 insertions(+), 57 deletions(-) diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm index ed6439d3cd..e10b1a89ce 100644 --- a/code/modules/client/asset_cache.dm +++ b/code/modules/client/asset_cache.dm @@ -308,7 +308,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the "nano/images/modular_computers/", "nano/js/" ) - var/list/uncommon_dirs = list( + var/list/template_dirs = list( "nano/templates/" ) @@ -321,18 +321,21 @@ You can set verify to TRUE if you want send() to sleep until the client has the if(fexists(path + filename)) common[filename] = fcopy_rsc(path + filename) register_asset(filename, common[filename]) - for(var/path in uncommon_dirs) + // Combine all templates into a single bundle. + var/list/template_data = list() + for(var/path in template_dirs) var/list/filenames = flist(path) for(var/filename in filenames) - if(copytext(filename, length(filename)) != "/") // Ignore directories. - if(fexists(path + filename)) - register_asset(filename, fcopy_rsc(path + filename)) + if(copytext(filename, length(filename) - 4) == ".tmpl") // Ignore directories. + template_data[filename] = file2text(path + filename) + var/template_bundle = "function nanouiTemplateBundle(){return [json_encode(template_data)];}" + var/fname = "data/nano_templates_bundle.js" + fdel(fname) + text2file(template_bundle, fname) + register_asset("nano_templates_bundle.js", fcopy_rsc(fname)) + fdel(fname) -/datum/asset/nanoui/send(client, uncommon) - if(!islist(uncommon)) - uncommon = list(uncommon) - - send_asset_list(client, uncommon) +/datum/asset/nanoui/send(client) send_asset_list(client, common) diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm index b7adabffa2..900f5b9d33 100644 --- a/code/modules/nano/nanoui.dm +++ b/code/modules/nano/nanoui.dm @@ -104,6 +104,7 @@ nanoui is used to open and update nano browser uis /datum/nanoui/proc/add_common_assets() add_script("libraries.min.js") // A JS file comprising of jQuery, doT.js and jQuery Timer libraries (compressed together) add_script("nano_utility.js") // The NanoUtility JS, this is used to store utility functions. + add_script("nano_templates_bundle.js") // Contains all templates, generated by asset cache system at server start. add_script("nano_template.js") // The NanoTemplate JS, this is used to render templates. add_script("nano_state_manager.js") // The NanoStateManager JS, it handles updates from the server and passes data to the current state add_script("nano_state.js") // The NanoState JS, this is the base state which all states must inherit from diff --git a/nano/js/nano_template.js b/nano/js/nano_template.js index f8f5d26594..b50df1281a 100644 --- a/nano/js/nano_template.js +++ b/nano/js/nano_template.js @@ -2,6 +2,7 @@ var NanoTemplate = function () { var _templateData = {}; + var _templateSources = {}; var _templates = {}; var _compiledTemplates = {}; @@ -15,59 +16,43 @@ var NanoTemplate = function () { if (_templateData == null) { alert('Error: Template data did not load correctly.'); - } - - loadNextTemplate(); - }; - - var loadNextTemplate = function () { - // we count the number of templates for this ui so that we know when they've all been rendered - var templateCount = Object.size(_templateData); - - if (!templateCount) - { - $(document).trigger('templatesLoaded'); - return; } - // load markup for each template and register it - for (var key in _templateData) - { - if (!_templateData.hasOwnProperty(key)) - { - continue; - } - - $.when($.ajax({ - url: _templateData[key], + if (('nanouiTemplateBundle' in window) && (typeof nanouiTemplateBundle === 'function')) { + _templateSources = nanouiTemplateBundle(); // From nanoui_templates.js + } + var templateLoadingPromises = $.map(_templateData, function(filename, key) { + var fetchSourcePromise; + if (_templateSources && _templateSources.hasOwnProperty(filename)) { + // Its in the bundle, just do it + fetchSourcePromise = $.Deferred().resolve(_templateSources[filename]).promise(); + } else { + // Otherwise fetch from ze network + fetchSourcePromise = $.ajax({ + url: filename, cache: false, dataType: 'text' - })) - .done(function(templateMarkup) { - - templateMarkup += '
'; - - try - { - NanoTemplate.addTemplate(key, templateMarkup); - } - catch(error) - { - alert('ERROR: An error occurred while loading the UI: ' + error.message); - return; - } - - delete _templateData[key]; - - loadNextTemplate(); - }) - .fail(function () { - alert('ERROR: Loading template ' + key + '(' + _templateData[key] + ') failed!'); }); + } - return; - } - } + return fetchSourcePromise.done(function(templateMarkup) { + templateMarkup += '
'; + try { + NanoTemplate.addTemplate(key, templateMarkup); + } catch(error) { + alert('ERROR: An error occurred while loading the UI: ' + error.message); + return; + } + }).fail(function () { + alert('ERROR: Loading template ' + key + '(' + _templateData[key] + ') failed!'); + }); + }); + + // Wait for all of them to be done and then trigger the event. + $.when.apply(this, templateLoadingPromises).done(function() { + $(document).trigger('templatesLoaded'); + }); + }; var compileTemplates = function () {