add ability to reload JavaScript on page transitions with enhanced navigation
This commit is contained in:
parent
32efeee4c7
commit
7f74e79253
|
@ -580,6 +580,7 @@
|
|||
ES6Module = resource.ES6Module,
|
||||
Content = resource.Content,
|
||||
RenderMode = resource.RenderMode,
|
||||
Reload = resource.Reload,
|
||||
Level = level,
|
||||
Namespace = name
|
||||
});
|
||||
|
|
|
@ -526,12 +526,20 @@
|
|||
{
|
||||
if (!string.IsNullOrEmpty(resource.Url))
|
||||
{
|
||||
var url = (resource.Url.Contains("://")) ? resource.Url : alias.BaseUrl + resource.Url;
|
||||
return "<script" +
|
||||
((!string.IsNullOrEmpty(resource.Integrity)) ? " integrity=\"" + resource.Integrity + "\"" : "") +
|
||||
((!string.IsNullOrEmpty(resource.CrossOrigin)) ? " crossorigin=\"" + resource.CrossOrigin + "\"" : "") +
|
||||
((resource.ES6Module) ? " type=\"module\"" : "") +
|
||||
" src =\"" + url + "\"></script>"; // src at end of element due to enhanced navigation patch algorithm
|
||||
if (!resource.Reload)
|
||||
{
|
||||
var url = (resource.Url.Contains("://")) ? resource.Url : alias.BaseUrl + resource.Url;
|
||||
return "<script" +
|
||||
((!string.IsNullOrEmpty(resource.Integrity)) ? " integrity=\"" + resource.Integrity + "\"" : "") +
|
||||
((!string.IsNullOrEmpty(resource.CrossOrigin)) ? " crossorigin=\"" + resource.CrossOrigin + "\"" : "") +
|
||||
((resource.ES6Module) ? " type=\"module\"" : "") +
|
||||
" src =\"" + url + "\"></script>"; // src at end of element due to enhanced navigation patch algorithm
|
||||
}
|
||||
else
|
||||
{
|
||||
// use custom element which can execute script on every page transition
|
||||
return "<page-script src=\"" + resource.Url + "\"></page-script>";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -684,6 +692,7 @@
|
|||
ES6Module = resource.ES6Module,
|
||||
Content = resource.Content,
|
||||
RenderMode = resource.RenderMode,
|
||||
Reload = resource.Reload,
|
||||
Level = level,
|
||||
Namespace = name
|
||||
});
|
||||
|
|
90
Oqtane.Server/wwwroot/Oqtane.Server.lib.module.js
Normal file
90
Oqtane.Server/wwwroot/Oqtane.Server.lib.module.js
Normal file
|
@ -0,0 +1,90 @@
|
|||
const pageScriptInfoBySrc = new Map();
|
||||
|
||||
function registerPageScriptElement(src) {
|
||||
if (!src) {
|
||||
throw new Error('Must provide a non-empty value for the "src" attribute.');
|
||||
}
|
||||
|
||||
let pageScriptInfo = pageScriptInfoBySrc.get(src);
|
||||
|
||||
if (pageScriptInfo) {
|
||||
pageScriptInfo.referenceCount++;
|
||||
} else {
|
||||
pageScriptInfo = { referenceCount: 1, module: null };
|
||||
pageScriptInfoBySrc.set(src, pageScriptInfo);
|
||||
initializePageScriptModule(src, pageScriptInfo);
|
||||
}
|
||||
}
|
||||
|
||||
function unregisterPageScriptElement(src) {
|
||||
if (!src) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pageScriptInfo = pageScriptInfoBySrc.get(src);
|
||||
if (!pageScriptInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
pageScriptInfo.referenceCount--;
|
||||
}
|
||||
|
||||
async function initializePageScriptModule(src, pageScriptInfo) {
|
||||
// If the path is relative, normalize it by by making it an absolute URL
|
||||
// with document's the base HREF.
|
||||
if (src.startsWith("./")) {
|
||||
src = new URL(src.substr(2), document.baseURI).toString();
|
||||
}
|
||||
|
||||
const module = await import(src);
|
||||
|
||||
if (pageScriptInfo.referenceCount <= 0) {
|
||||
// All page-script elements with the same 'src' were
|
||||
// unregistered while we were loading the module.
|
||||
return;
|
||||
}
|
||||
|
||||
pageScriptInfo.module = module;
|
||||
module.onLoad?.();
|
||||
module.onUpdate?.();
|
||||
}
|
||||
|
||||
function onEnhancedLoad() {
|
||||
// Start by invoking 'onDispose' on any modules that are no longer referenced.
|
||||
for (const [src, { module, referenceCount }] of pageScriptInfoBySrc) {
|
||||
if (referenceCount <= 0) {
|
||||
module?.onDispose?.();
|
||||
pageScriptInfoBySrc.delete(src);
|
||||
}
|
||||
}
|
||||
|
||||
// Then invoke 'onUpdate' on the remaining modules.
|
||||
for (const { module } of pageScriptInfoBySrc.values()) {
|
||||
module?.onUpdate?.();
|
||||
}
|
||||
}
|
||||
|
||||
export function afterWebStarted(blazor) {
|
||||
customElements.define('page-script', class extends HTMLElement {
|
||||
static observedAttributes = ['src'];
|
||||
|
||||
// We use attributeChangedCallback instead of connectedCallback
|
||||
// because a page-script element might get reused between enhanced
|
||||
// navigations.
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
if (name !== 'src') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.src = newValue;
|
||||
unregisterPageScriptElement(oldValue);
|
||||
registerPageScriptElement(newValue);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
unregisterPageScriptElement(this.src);
|
||||
}
|
||||
});
|
||||
|
||||
blazor.addEventListener('enhancedload', onEnhancedLoad);
|
||||
}
|
|
@ -67,6 +67,11 @@ namespace Oqtane.Models
|
|||
/// </summary>
|
||||
public string RenderMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that a script should be reloaded on every page transition - not applicable to Stylesheets
|
||||
/// </summary>
|
||||
public bool Reload { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The namespace of the component that declared the resource - only used in SiteRouter
|
||||
/// </summary>
|
||||
|
|
Loading…
Reference in New Issue
Block a user