From 983baf4e34d96a6a9b93a37d7f1c68165973b21b Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Sat, 25 Apr 2020 20:33:12 +0800 Subject: [PATCH] MDL-68524 js: Add prefetch module --- lib/amd/build/prefetch.min.js | Bin 0 -> 2720 bytes lib/amd/build/prefetch.min.js.map | Bin 0 -> 7961 bytes lib/amd/build/templates.min.js | Bin 8933 -> 9354 bytes lib/amd/build/templates.min.js.map | Bin 71511 -> 74898 bytes lib/amd/src/prefetch.js | 194 +++++++++++++++++++++++++++++ lib/amd/src/templates.js | 65 +++++++++- lib/outputrequirementslib.php | 3 + 7 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 lib/amd/build/prefetch.min.js create mode 100644 lib/amd/build/prefetch.min.js.map create mode 100644 lib/amd/src/prefetch.js diff --git a/lib/amd/build/prefetch.min.js b/lib/amd/build/prefetch.min.js new file mode 100644 index 0000000000000000000000000000000000000000..eee33e0fbe41ef72f64adc389dc16fb988e22c4c GIT binary patch literal 2720 zcmds3O^@3)5WVMDXjQ-v5tZv6dXcIcIpk2FX^ZamWEch|(K2m{)RL54L#zLu8GX8r z6XcK{+6yU>GegeIo5#udPAKjLex?n7tPJ0Am+k#zCklTP?rN1e zp;f@blr(;Axo4dbne*e{(*w^O%{!Za7+rDWE+FS`x7>cvc`dmgHYX-)9z85u5;K%# zwRFizi`-krX)>E9jp42~%43TKqqB(>i<&_#Vr?6wBt9|Y6^UP~{^;C)NZh63dgq;m z%Jq5GPtiRI%jIr`!`XgY-HUN~-8D!C_=bxdX4zp{zPG-4M#UCLBT z+Q~X?K-TLM&|Sk{>n8 znXfPvfX-4_9*jyonhR?9ODzl!);;PmIg&YU0r-gbmfS^2**PLo9IdRr15~rgoP8HM0}7eRB>Zu?ByFf>RN-3$4*}!{2nVPnEAHQcn=5MYH$R0YP%VS(JnL?o!ytOQtgNfn-bKC;n>N}K&?pA zP%Jf`Dop`oq zs=$|P(%%BpmT1K8^;vR@%^iN0(EFj-+>SN3ydLTBcF9I+T6^m1KYF=Yuu;_xHSA5s jftTMrK7Qv}U7L)50E&lb{PpLr$#?)Qg#vm&wtw>xuu9Nr literal 0 HcmV?d00001 diff --git a/lib/amd/build/prefetch.min.js.map b/lib/amd/build/prefetch.min.js.map new file mode 100644 index 0000000000000000000000000000000000000000..66563ea2e0590d216c56d830c5740634442f2bb0 GIT binary patch literal 7961 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 Tlh=9p2WP>pxd>zaulw;|4jRfq literal 0 HcmV?d00001 diff --git a/lib/amd/build/templates.min.js b/lib/amd/build/templates.min.js index aefca081876fc82a5f82f3c6d7d205178c5b9ecf..d7d76f4fc73b64d829769214a03cebe78deec848 100644 GIT binary patch delta 350 zcmZvX&q~BF5XM0S>wUomMZ+E>p&?$SC7$#k;%#3bO(#vHO-q`pYboBn_6fXs6!zr9 zh$r8}>@FVs!yM*gzL{_MeO^3WzP?4sfdVh}9IB=i9$KzCE4`^L7F3d6j0fBM$1bWTru5*(=cCE^u`_uDR)Q_O{;{XHU~N+xk3$xr1y`)q zMtMxA4*I4xcI~7cYr0nBUe;ApTd+PUs1+3?ntBbPOWJ~PQeVL$$!Q({oP#{c*!f28 z=9mnj(#7&6I-Q<1zZsKnM)b!D)EVhlT#{S3Ll5bAeYh8gS;h;t{y%Ksk!1f~FW*tL F^#yy{eGdQt delta 17 YcmeD3eCoPkC&%X7oaz#rTa{Ru07s7orT_o{ diff --git a/lib/amd/build/templates.min.js.map b/lib/amd/build/templates.min.js.map index 3a6b52c2f13a2e3a10b9254715129e9935307c29..b95cb3a6399dd5944d21144c8e483ff02ed255ad 100644 GIT binary patch delta 5451 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 delta 4140 zcmbVPYiwJ071uSPBI}%VO`5iOIC0xNeH+{HJ0VT(|K96s$4Q$s?=0y^)7Ew#jvYJB zV-wXn0n;P~-5KKJI?$v|u(c3DVH!o^+n6Rz+5l++b$sIk5`37D3e(0p=btVnD{SJ6 z?fdunpU3a~&f`A!X4xNJE4%e%+0IL4caMKLZD>gYMmlS%#?^UE%LrB1v=v<))wIzJ zyybjO@xX->?aCTFePXV9ULC(Llaw+(0dsRll?{00g_2$ALsk4 z@Wh0(Hf5-BO}j)VE5g60UN6G!iB|Ob?nF=tfUP;I)44RS;)u!^AW*5SkE2nN*Ia;7oMaA+C{Nat7hWRec_W%zqX4ZPSAMhow^v?4~T z+URCI7718e{9EE7RmsRqHKA!|RZG(rR$;ic3w={nhx;5|8s(cglfFLZ<~yxEdGk0% zh2n9(%F*1v39}9L2TV;%iX_ansY(%^X=|v-N7c&&f~lp1i+o%X5n~a4)%ME=;8U4r zGkJ?-Up6}@W0&t$i z#Pzvam2H9&zUexltimg-eA!7Ehdret_tL_HH3okm4V*Y;Sp0%eqUAuV(ho?i?gt(^#|IK2$Pu8go>8=L~& zWr54za8(wiObffCZ<<8C_!8%pNvC%SbwSh4Qz+{q#IP1w%K#lM5ioj0lvbxy%VgvH zFO;fVX4UkkZr@}G37tfBe33BG^iG?kd>Su{;aWC^aoE6)t?5! z)mhdi(Hsv0H~Ac;d|UA( zwD%2X)Du@^FT)LeBfZ9>@@=ivhXaRrYw@sd$9zdE*R_`v%6*YB0+r>UhRFlaVbJU4Z>jICw9J@P42bX<&u4CQAH8UXm zaHCIELhyE9M{}CZa^fr=5Hg3zNmR+{PKqGZ_xDSS&ZVe2a({S+1zYp(S=$n6_+EcY zOYC?u}SMbgc{M$MM1=KiHHS@T0JK7TUu}1Hlrz9(?)`# z=a`Zr#3p4oNa|_$s}@CVH_dkJN^>Gui=dH!y zFgOHEL(BpH5|7y222|+5s`Z3AscGzSQZONXFsUc8+<&c)R)@H@e5BJLjLcZrfEFW2 zY`$RBV?91@j8sX|;5@0T8n!w=U? z_0y5^&3GlOB9V z=>TsbaUVkUmep2j|JZ)}Gh}`mt&ha&rS%Y750+T(K;HZ~)-8=;&-_x{`EV*P=CPZ& zied~29IwFww&I;Q;)?j`gO}p{m8&u8q7lY!#mK;i@zWiCW&qU?woc9fk_KU=zNJ&D zvKwL=zml7f7?`hE=7!E1^l$=RA87I~4iJYVZE(C`F{H#2C%I$@TA7lIt^`yhhN^sA zmr_V-^g||b0vD0%i5evbFDEkpMW#l{K>y$omT|(yVA#INy7)t1f;R@8_P`eVo!=H0 z3l{aYt6LVWHgb*4$rW{xYk~Q{MXu`wV~LNXSG+1&A$DCBOg=`u-E9I47xgbANdB7z zV`Z_qQnAAaj$uB#RuW>k$&8vZk#`k+I~M0K7#B< z9&Hn)CV1Z;&*(WgdA`RR8X%9j`{TTzcZx8RhC|q0Mhxy^y!Pr@_|Ewb)cX4QHLRc0 zqk+mCrw56LWqvjihumm}7M?$kHXuDd8GXu`UcHjc>gbON4Ez+c6pvSVzs{iA)rDn3J z*%K!Mu!fc0zRh8BUyjbB0dpn?k51NNGK!O@>pT_>7?xjqSr5VCsS6dG46ZCoEcCBWHB}Y&hDDkZYF=E2pG=*xuQ5ID*WO1{&ho`D*PcHN zEz^@. + +/** + * Prefetch module to help lazily load content for use on the current page. + * + * @module core/prefetch + * @class prefetch + * @package core + * @copyright 2020 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +import Config from 'core/config'; + +// Keep track of whether the initial prefetch has occurred. +let initialPrefetchComplete = false; + +// Prefetch templates. +let templateList = []; + +// Prefetch strings. +let stringList = {}; + +let prefetchTimer; + +/** + * Fetch all queued items in the queue. + * + * Should only be called via processQueue. + */ +const fetchQueue = () => { + // Prefetch templates. + if (templateList) { + const templatesToLoad = templateList.slice(); + templateList = []; + import('core/templates') + .then(Templates => Templates.prefetchTemplates(templatesToLoad)) + .catch(); + } + + // Prefetch strings. + const mappedStringsToFetch = stringList; + stringList = {}; + + const stringsToFetch = []; + Object.keys(mappedStringsToFetch).forEach(component => { + stringsToFetch.push(...mappedStringsToFetch[component].map(key => { + return {component, key}; + })); + }); + + if (stringsToFetch) { + import('core/str') + .then(Str => Str.get_strings(stringsToFetch)) + .catch(); + } +}; + +/** + * Process the prefetch queues as required. + * + * The initial call will queue the first fetch after a delay. + * Subsequent fetches are immediate. + */ +const processQueue = () => { + if (Config.jsrev <= 0) { + // No point pre-fetching when cachejs is disabled as we do not store anything in the cache anyway. + return; + } + + if (prefetchTimer) { + // There is a live prefetch timer. The initial prefetch has been scheduled but is not complete. + return; + } + + // The initial prefetch has compelted. Just queue as normal. + if (initialPrefetchComplete) { + fetchQueue(); + + return; + } + + // Queue the initial prefetch in a short while. + prefetchTimer = setTimeout(() => { + initialPrefetchComplete = true; + prefetchTimer = null; + + // Ensure that the icon system is loaded. + // This can be quite slow and delay UI interactions if it is loaded on demand. + import(Config.iconsystemmodule) + .then(IconSystem => { + const iconSystem = new IconSystem(); + prefetchTemplate(iconSystem.getTemplateName()); + + return iconSystem; + }) + .then(iconSystem => { + fetchQueue(); + iconSystem.init(); + + return; + }) + .catch(); + }, 500); +}; + +/** + * Add a set of templates to the prefetch queue. + * + * @param {Array} templatesNames + */ +const prefetchTemplates = templatesNames => { + templateList = templateList.concat(templatesNames); + + processQueue(); +}; + +/** + * Add a single template to the prefetch queue. + * + * @param {String} templateName + * @returns {undefined} + */ +const prefetchTemplate = templateName => prefetchTemplates([templateName]); + +/** + * Add a set of strings from the same component to the prefetch queue. + * + * @param {String} component + * @param {String[]} keys + */ +const prefetchStrings = (component, keys) => { + if (!stringList[component]) { + stringList[component] = []; + } + + stringList[component] = stringList[component].concat(keys); + + processQueue(); +}; + +/** + * Add a single string to the prefetch queue. + * + * @param {String} component + * @param {String} key + */ +const prefetchString = (component, key) => { + if (!stringList[component]) { + stringList[component] = []; + } + + stringList[component].push(key); + + processQueue(); +}; + +// Prefetch some commonly-used templates. +prefetchTemplates([].concat( + ['core/loading'], + ['core/modal'], + ['core/modal_backdrop'], +)); + +// And some commonly used strings. +prefetchStrings('core', [ + 'cancel', + 'closebuttontitle', + 'loading', + 'savechanges', +]); +prefetchStrings('core_form', [ + 'showless', + 'showmore', +]); + +export default { + prefetchTemplate, + prefetchTemplates, + prefetchString, + prefetchStrings, +}; diff --git a/lib/amd/src/templates.js b/lib/amd/src/templates.js index afac7f3aed0..8ac79ab3462 100644 --- a/lib/amd/src/templates.js +++ b/lib/amd/src/templates.js @@ -298,7 +298,7 @@ define([ return cachedPromise; } - // Check the buffer to seee if this template has already been added. + // Check the buffer to see if this template has already been added. var existingBufferRecords = loadTemplateBuffer.filter(function(record) { return record.searchKey == searchKey; }); @@ -329,6 +329,50 @@ define([ return deferred.promise(); }; + /** + * Prefetch a set of templates without rendering them. + * + * @param {Array} templateNames The list of templates to fetch + * @param {String} currentTheme + */ + Renderer.prototype.prefetchTemplates = function(templateNames, currentTheme) { + templateNames.forEach(function(templateName) { + var searchKey = currentTheme + '/' + templateName; + + // If we haven't already seen this template then buffer it. + if (getTemplatePromiseFromCache(searchKey)) { + return; + } + + // Check the buffer to see if this template has already been added. + var existingBufferRecords = loadTemplateBuffer.filter(function(record) { + return record.searchKey == searchKey; + }); + + if (existingBufferRecords.length) { + // This template is already in the buffer so just return the existing promise. + // No need to add it to the buffer again. + return; + } + + // This is the first time this has been requested so let's add it to the buffer to be loaded. + var parts = templateName.split('/'); + var component = parts.shift(); + var name = parts.join('/'); + + // Add this template to the buffer to be loaded. + loadTemplateBuffer.push({ + component: component, + name: name, + theme: currentTheme, + searchKey: searchKey, + deferred: $.Deferred(), + }); + }); + + processLoadTemplateBuffer(); + }; + /** * Load a partial from the cache or ajax. * @@ -1045,6 +1089,25 @@ define([ return renderer.render(templateName, context, themeName); }, + /** + * Prefetch a set of templates without rendering them. + * + * @method getTemplate + * @param {Array} templateNames The list of templates to fetch + * @param {String} themeName + * @returns {Promise} + */ + prefetchTemplates: function(templateNames, themeName) { + var renderer = new Renderer(); + + if (typeof themeName === "undefined") { + // System context by default. + themeName = config.theme; + } + + return renderer.prefetchTemplates(templateNames, themeName); + }, + /** * Every call to render creates a new instance of the class and calls render on it. This * means each render call has it's own class variables. diff --git a/lib/outputrequirementslib.php b/lib/outputrequirementslib.php index 961fda184bf..236b0ed139a 100644 --- a/lib/outputrequirementslib.php +++ b/lib/outputrequirementslib.php @@ -1390,6 +1390,9 @@ class page_requirements_manager { // First include must be to a module with no dependencies, this prevents multiple requests. $prefix = 'M.util.js_pending("core/first");'; $prefix .= "require(['core/first'], function() {\n"; + if ($cachejs) { + $prefix .= "require(['core/prefetch']);\n"; + } $suffix = 'M.util.js_complete("core/first");'; $suffix .= "\n});"; $output .= html_writer::script($prefix . implode(";\n", $this->amdjscode) . $suffix); -- 2.43.0