rendering optimizations

This commit is contained in:
sbwalker
2025-06-05 09:31:54 -04:00
parent 985e50d415
commit 4418e27c29
9 changed files with 74 additions and 33 deletions

View File

@ -20,6 +20,7 @@
protected override void OnParametersSet()
{
// trim PageState to mitigate page bloat caused by Blazor serializing/encrypting state when crossing render mode boundaries
// only include properties required by the ModuleActionsInteractive component
_pageState = new PageState
{
Alias = PageState.Alias,

View File

@ -91,6 +91,7 @@
}
// trim PageState to mitigate page bloat caused by Blazor serializing/encrypting state when crossing render mode boundaries
// only include properties required by the ControlPanelInteractive component
_pageState = new PageState
{
Alias = PageState.Alias,

View File

@ -6,7 +6,7 @@
@if (ComponentType != null && _visible)
{
<a id="@ModuleState.PageModuleId.ToString()"></a>
<CascadingValue Value="@ModuleState">
<CascadingValue Value="@ModuleState" IsFixed="true">
@if (_useadminborder)
{
<div class="app-pane-admin-border">

View File

@ -10,11 +10,11 @@
@((MarkupString)_comment)
@if (PageState.RenderMode == RenderModes.Interactive || ModuleState.RenderMode == RenderModes.Static)
{
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" />
<RenderModeBoundary ModuleState="@ModuleState" PageState="@_pageState" SiteState="@SiteState" />
}
else
{
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" @rendermode="InteractiveRenderMode.GetInteractiveRenderMode(PageState.Site.Runtime, _prerender)" />
<RenderModeBoundary ModuleState="@ModuleState" PageState="@_pageState" SiteState="@SiteState" @rendermode="InteractiveRenderMode.GetInteractiveRenderMode(PageState.Site.Runtime, _prerender)" />
}
}
@if (PageState.ModuleId == -1)
@ -32,6 +32,7 @@
private bool _prerender;
private string _comment;
private PageState _pageState;
protected override void OnParametersSet()
{
@ -48,11 +49,12 @@
}
_comment += " -->";
_pageState = PageState.Clone();
if (PageState.RenderMode == RenderModes.Static && ModuleState.RenderMode == RenderModes.Interactive)
{
// trim PageState to mitigate page bloat caused by Blazor serializing/encrypting state when crossing render mode boundaries
// please note that this performance optimization results in the PageState.Pages property not being available for use in Interactive components
PageState.Site.Pages = new List<Page>();
// please note that this performance optimization results in the PageState.Pages property not being available for use in downstream Interactive components
_pageState.Site.Pages = new List<Page>();
}
}

View File

@ -37,5 +37,34 @@ namespace Oqtane.UI
{
get { return Site?.Languages; }
}
public PageState Clone()
{
return new PageState
{
Alias = Alias,
Site = Site,
Page = Page,
Modules = Modules,
User = User,
Uri = Uri,
Route = Route,
QueryString = QueryString,
UrlParameters = UrlParameters,
ModuleId = ModuleId,
Action = Action,
EditMode = EditMode,
LastSyncDate = LastSyncDate,
RenderMode = RenderMode,
Runtime = Runtime,
VisitorId = VisitorId,
RemoteIPAddress = RemoteIPAddress,
ReturnUrl = ReturnUrl,
IsInternalNavigation = IsInternalNavigation,
RenderId = RenderId,
Refresh = Refresh,
AllowCookies = AllowCookies
};
}
}
}

View File

@ -29,7 +29,7 @@ else
RenderFragment DynamicComponent { get; set; }
protected override void OnParametersSet()
{
{
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList) && PageState.Action == Constants.DefaultAction)
{
_useadminborder = true;
@ -45,12 +45,6 @@ else
{
foreach (Module module in PageState.Modules)
{
// set renderid - this allows the framework to determine which components should be rendered when PageState changes
if (module.RenderId != PageState.RenderId)
{
module.RenderId = PageState.RenderId;
}
var pane = module.Pane;
if (module.ModuleId == PageState.ModuleId && PageState.Action != Constants.DefaultAction)
{
@ -101,7 +95,7 @@ else
if (authorized)
{
CreateComponent(builder, module, module.PageModuleId);
CreateComponent(builder, module);
}
}
}
@ -112,7 +106,7 @@ else
// check if user is authorized to view module
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.PermissionList))
{
CreateComponent(builder, module, -1);
CreateComponent(builder, module);
}
}
}
@ -121,14 +115,11 @@ else
};
}
private void CreateComponent(RenderTreeBuilder builder, Module module, int key)
private void CreateComponent(RenderTreeBuilder builder, Module module)
{
builder.OpenComponent(0, typeof(ContainerBuilder));
builder.AddAttribute(1, "ModuleState", module);
if (key != -1)
{
builder.SetKey(module.PageModuleId);
}
builder.SetKey(module.PageModuleId);
builder.CloseComponent();
}
}

View File

@ -4,8 +4,8 @@
@inject ILogService LoggingService
@inherits ErrorBoundary
<CascadingValue Value="@PageState">
<CascadingValue Value="@ModuleState">
<CascadingValue Value="@PageState" IsFixed="true">
<CascadingValue Value="@ModuleState" IsFixed="true">
@if (CurrentException is null)
{
@if (ModuleType != null)

View File

@ -48,12 +48,18 @@
private bool _initialized = false;
private bool _installed = false;
private string _display = "display: none;";
private string _display = "";
private PageState _pageState { get; set; }
protected override async Task OnParametersSetAsync()
{
if (PageState != null && PageState.RenderMode == RenderModes.Interactive && PageState.Site.Prerender)
{
// prevents flash on initial interactive page load when using prerendering
_display = "display: none;";
}
SiteState.AntiForgeryToken = AntiForgeryToken;
SiteState.AuthorizationToken = AuthorizationToken;
SiteState.Platform = Platform;
@ -61,7 +67,7 @@
if (Runtime == Runtimes.Hybrid)
{
var installation = await InstallationService.IsInstalled();
var installation = await InstallationService.IsInstalled();
_installed = installation.Success;
if (installation.Alias != null)
{
@ -73,8 +79,8 @@
if (PageState != null)
{
_pageState = PageState;
SiteState.Alias = PageState.Alias;
SiteState.RemoteIPAddress = (PageState != null) ? PageState.RemoteIPAddress : "";
SiteState.Alias = _pageState.Alias;
SiteState.RemoteIPAddress = _pageState.RemoteIPAddress;
_installed = true;
}
}
@ -85,9 +91,7 @@
{
if (firstRender)
{
// prevents flash on initial interactive page load
_display = "";
StateHasChanged();
}
}

View File

@ -71,7 +71,7 @@
{
if (PageState == null || PageState.Refresh)
{
await Refresh();
await Refresh(false);
}
}
@ -79,7 +79,7 @@
{
_absoluteUri = args.Location;
_isInternalNavigation = true;
await Refresh();
await Refresh(true);
}
Task IHandleAfterRender.OnAfterRenderAsync()
@ -93,7 +93,7 @@
}
[SuppressMessage("ReSharper", "StringIndexOfIsCultureSpecific.1")]
private async Task Refresh()
private async Task Refresh(bool locationChanged)
{
Site site = null;
Page page = null;
@ -103,6 +103,7 @@
var refresh = false;
var lastsyncdate = DateTime.MinValue;
var visitorId = -1;
var renderid = Guid.Empty;
_error = "";
Route route = new Route(_absoluteUri, SiteState.Alias.Path);
@ -288,11 +289,21 @@
modules = PageState.Modules;
}
// renderid allows the framework to determine which module components should be rendered on a page
if (PageState == null || locationChanged)
{
renderid = Guid.NewGuid();
}
else
{
renderid = PageState.RenderId;
}
// load additional metadata for current page
page = ProcessPage(page, site, user, SiteState.Alias, action);
// load additional metadata for modules
(page, modules) = ProcessModules(site, page, modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType, SiteState.Alias);
(page, modules) = ProcessModules(site, page, modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType, SiteState.Alias, renderid);
//cookie consent
var _allowCookies = PageState?.AllowCookies;
@ -324,7 +335,7 @@
RemoteIPAddress = SiteState.RemoteIPAddress,
ReturnUrl = returnurl,
IsInternalNavigation = _isInternalNavigation,
RenderId = Guid.NewGuid(),
RenderId = renderid,
Refresh = false,
AllowCookies = _allowCookies.GetValueOrDefault(true)
};
@ -447,7 +458,7 @@
return page;
}
private (Page Page, List<Module> Modules) ProcessModules(Site site, Page page, List<Module> modules, int moduleid, string action, string defaultcontainertype, Alias alias)
private (Page Page, List<Module> Modules) ProcessModules(Site site, Page page, List<Module> modules, int moduleid, string action, string defaultcontainertype, Alias alias, Guid renderid)
{
var paneindex = new Dictionary<string, int>();
@ -592,6 +603,8 @@
{
module.ContainerType = defaultcontainertype;
}
module.RenderId = renderid;
}
foreach (Module module in modules.Where(item => item.PageId == page.PageId))