lovesomekunicki
lovesomekunicki

Reputation: 131

Blazor Server - Large Page Weight

I've noticed in my blazor server applications that sometimes the page weight can get bloated.

For example, I have a page with a long list, each list item has many components. When I inspect the page in dev tools and save the html as text, the saved file might be 500kb in size. When I inspect the websocket connection and watch the messages, the message that returns the html for the page might be 1000kb or larger. I'm thinking this has something to do with javascript that is injected but am unsure.

Has anyone else noticed this and found solutions?

---- Update ----

It was pointed out I didn't provide sample code, good point! Here's the razor code in question, _itemsSorted could be up to 1000 items.

@foreach (var item in _itemsSorted)
{
    <div class="rounded d-flex flex-row justify-content-between @GetItemCssClasses(item)" id="[email protected]">
        <div>
            <div class="d-flex align-items-center">
                @item.Text
                @if (item.Attributes.HasAttribute(Constants.item_Category))
                {
                    string categoryName = GetCategoryDisplayName(Convert.ToInt32(item.Attributes.GetAttributeValue(Constants.item_Category)));
                    if (!string.IsNullOrEmpty(categoryName))
                    {
                        <span>&nbsp;&nbsp;</span><span class="badge badge-default badge-small">@categoryName</span>
                    }
                }
                @if (!item.Active)
                {
                    <span>&nbsp;&nbsp;</span><span class="badge badge-warning badge-small">Inactive</span>
                }
                @if (item.Attributes.HasAttribute(Constants.Ignore) && item.Attributes.GetAttributeValue(Constants.Ignore) == "1")
                {
                    <span>&nbsp;&nbsp;</span><span class="badge badge-danger badge-small">Ignore</span>
                }
            </div>

            @if (item.itemType != itemTypes.Folder && !string.IsNullOrEmpty(item.SubText))
            {
                <div class="text-muted">
                    @item.SubText
                </div>
            }
        </div>
        <div class="text-nowrap ml-2">
  
            <button class="@GetButtonsCssClasses(item)" title="@moveUpTitle" @onclick="@(e=> MoveUp(item))" disabled="@moveUpDisabled"><span class="fas fa-arrow-up"></span></button>
            <button class="@GetButtonsCssClasses(item)" title="@moveDownTitle" @onclick="@(e=> MoveDown(item))" disabled="@moveDownDisabled"><span class="fas fa-arrow-down"></span></button>
            <button class="@GetButtonsCssClasses(item)" title="Move to a new location" @onclick="@(e=> ShowMoveModal(item))" disabled="@_savingMoveStarted"><span class="fas fa-exchange-alt"></span></button>
            <button class="@GetButtonsCssClasses(item)" title="Edit this item" @onclick="@(e=> ShowEdititemModal(item))" disabled="@_savingMoveStarted"><span class="fas fa-edit"></span></button>
            @if (!_photoListInUse)
            {
                <button class="@GetButtonsCssClasses(item)" title="Delete this item" @onclick="@(e => ShowConfirmDeleteitemModal(item))" disabled="@_savingMoveStarted"><span class="fas fa-trash"></span></button>
            }
            <div class="d-inline">
                <button class="@GetButtonsCssClasses(item)" data-toggle="dropdown" title="Add new item" disabled="@_savingMoveStarted"><span class="fas fa-plus"></span></button>
                <div class="dropdown-menu pl-2 font-weight-normal" style="width:200px;">
                    @if (showAddFolderAbove)
                    {
                        <a href="" @onclick:preventDefault @onclick="@(e=> ShowInsertItemModal(item, itemTypes.Folder, false, false))" class="text-dark px-2 py-1 d-block"><span class="fas fa-folder-plus"></span>&nbsp;&nbsp;Insert <b>folder</b> above</a>
                    }
                    @if (showAddSubfolderAbove)
                    {
                        <a href="" @onclick:preventDefault @onclick="@(e=> ShowInsertItemModal(item, itemTypes.Folder, true, false))" class="text-dark px-2 py-1 d-block"><span class="fas fa-folder-plus"></span>&nbsp;&nbsp;Insert <b>subfolder</b> above</a>
                    }
                    @if (showAddPhotoAbove)
                    {
                        <a href="" @onclick:preventDefault @onclick="@(e=> ShowInsertItemModal(item, itemTypes.Photo, false, false))" class="text-dark px-2 py-1 d-block"><span class="fas fa-image"></span>&nbsp;&nbsp;Insert <b>photo</b> above</a>
                    }
                    <hr />
                    @if (showAddFolderBelow)
                    {
                        <a href="" @onclick:preventDefault @onclick="@(e=> ShowInsertItemModal(item, itemTypes.Folder, false, true))" class="text-dark px-2 py-1 d-block"><span class="fas fa-folder-plus"></span>&nbsp;&nbsp;Insert <b>folder</b> below</a>
                    }
                    @if (showAddSubfolderBelow)
                    {
                        <a href="" @onclick:preventDefault @onclick="@(e=> ShowInsertItemModal(item, itemTypes.Folder, true, true))" class="text-dark px-2 py-1 d-block"><span class="fas fa-folder-plus"></span>&nbsp;&nbsp;Insert <b>subfolder</b> below</a>
                    }
                    @if (showAddPhotoBelow)
                    {
                        <a href="" @onclick:preventDefault @onclick="@(e=> ShowInsertItemModal(item, itemTypes.Photo, false, true))" class="text-dark px-2 py-1 d-block"><span class="fas fa-image"></span>&nbsp;&nbsp;Insert <b>photo</b> below</a>
                    }
                </div>
            </div>
            <div class="d-inline">
                <button type="button" class="@GetButtonsCssClasses(item)" data-toggle="dropdown" title="Additional settings"><span class="fas fa-ellipsis-h"></span></button>
                <div class="dropdown-menu pl-2" style="width:200px;">
                    <div class="h6">Categories</div>
                    <a href="" @onclick="@(e=> ShowSelectCategoryModal(item))" @onclick:preventDefault class="text-dark px-2 py-1 d-block font-weight-normal" title="Categorize"><span class="fas fa-list text-dark"></span>&nbsp;&nbsp;Categorize</a>
                    <a href="" @onclick="@(e=> RemoveCategoryFromItem(item))" @onclick:preventDefault class="text-dark px-2 py-1 d-block font-weight-normal" title="Uncategorize"><span class="ion ion-md-close text-dark"></span>&nbsp;&nbsp;Uncategorize</a>
                    @if (PlType == ePlTypes.Package.ToInt32() || PlType == PlsViewModel.SiteOwnerPlTypeValue)
                    {
                        <div class="dropdown-divider"></div>
                        <div class="h6 pt-2">Closeout Settings</div>
                        <a href="" @onclick="@(e=> Exclude(item, true))" @onclick:preventDefault class="text-dark px-2 py-1 d-block font-weight-normal" title="Exclude."><span class="fas fa-ban text-dark"></span>&nbsp;&nbsp;Exclude</a>
                        <a href="" @onclick="@(e=> Exclude(item, false))" @onclick:preventDefault class="text-dark px-2 py-1 d-block font-weight-normal" title="Include."><span class="fas fa-check-circle text-dark"></span>&nbsp;&nbsp;Include</a>
                    }
                    @if (item.itemType == itemTypes.Folder)
                    {
                        <div class="dropdown-divider"></div>

                        <a href="" @onclick="@(e=> ShowDuplicateFolderModal(item))" @onclick:preventDefault class="text-dark px-2 py-1 d-block font-weight-normal" title="Duplicate Folder."><span class="fas fa-copy text-dark"></span>&nbsp;&nbsp;Duplicate Folder</a>
                    }
                </div>
            </div>
        </div>
    </div>

}

Upvotes: 0

Views: 381

Answers (1)

MrC aka Shaun Curtis
MrC aka Shaun Curtis

Reputation: 30046

You haven't shown the logic for getting _itemsSorted which may be the root cause of your problems. From what you've shown, you can use @key to help the renderer identify items in a loop and not re-render them unnecessarily

@foreach (var item in _itemsSorted)
{
    <div class="rounded d-flex flex-row justify-content-between @GetItemCssClasses(item)" id="[email protected]" @key=item>

On form design, consider using components for any repeated render blocks. For example links with @if could be refactored into a component something similar to this:

ConditionalLinkControl.razor

@if (Show)
{
    <a href="" @onclick:preventDefault @onclick="e=> this.OnClickEvent(1)" class="text-dark px-2 py-1 d-block"><span class="fas @this.IconClass"></span>@this.Label</a>
}

@code {

    [Parameter] public bool Show { get; set; }

    [Parameter] public EventCallback<int> OnClick { get; set; }

    [Parameter] public string IconClass { get; set; } = "fa-folder-plus";

    [Parameter] public MarkupString Label { get; set; }

    private void OnClickEvent(int item)
    {
        if (this.OnClick.HasDelegate)
            this.OnClick.InvokeAsync(item);
    }
}

which you then use as:

<ConditionalLinkControl Show"@ShowFolderAbove" OnClick="LinkEventHandler"/>

Upvotes: 1

Related Questions