.Net blazor webassembly startup loading 구현 비교

Published Dec 8, 2023 | Updated Feb 2, 2024 | 0 comments

Blazor 로 구현하는 경우 Server 부하를 줄이기 위해 WebAssembly 형태로 구현한 경우 고려할 사항이 있습니다.
사용자 PC 에 다운로드 되는 시간이 소요되기 때문에 처음 접속 시 상대적으로 기다려야 하는 시간이 늘어나게 됩니다.
이때, 용량이 크거나 네트워크 상태로 인해 접속 시간이 길어지면 사용자는 기다리지 않고 이탈하게 됩니다.
그래서, 다운로드가 완료되고 화면에 표시되기 전까지 로딩중임을 표현하게 됩니다.

.net 6 으로 구현할 당시에는 Visual Studio 기본 템플릿에서 디자인 추가 및 코드 수정이 필요했었습니다.
그리고 .net 7 에서는 Visual Studio 기본 템플릿에 진행율을 표시하는 디자인 및 css 코드가 추가되었습니다.
그런데, 이번에 .net 8 로 넘어가면서 Blazor Web App Template 으로 마이그레이션 하고
InteractiveWebAssemblyRenderMode 로 수정하게 되었습니다.
하지만 이상하게도 Visual Studio 기본 템플릿으로 생성된 코드에는 진행율을 표시하는 코드가 존재하지 않습니다.
(차후에 추가가 될지도 모르지만 2023-12-06 일 기준입니다.)
그래서 버전 별로 구현 방법 및 차이점을 비교해서 살펴보겠습니다.

프로젝트 생성

Visual Studio 2022 에서 기본 템플릿으로 생성해서 간단하게 살펴보겠습니다.
다음과 같이 프로젝트를 생성해 주세요.

솔루션 폴더로 다음과 같이 구분하겠습니다.

.Net 6 Blazor WebAssembly App

Client 프로젝트의 wwwroot 폴더에 있는 index.html 파일의 내용입니다.
기본 템플릿으로 생성된 코드에서 16 번째 라인부터 35 라인이 추가된 코드 입니다.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>DotNet6BlazorWebAssemblyAppGroup</title>
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/app.css" rel="stylesheet" />
    <link href="DotNet6BlazorWebAssemblyAppGroup.Client.styles.css" rel="stylesheet" />
</head>

<body>
    <div id="app">
        <div class="container-fluid"
             style="position:fixed;
             width: 100%;
             height: 100%;
             display: flex;
             align-items: center;
             justify-content: center;
             background-size: 400% 400%;
             background-image: linear-gradient(45deg, #24a3df 0%, #1430bd 25%, #8c2faf 50%, #e70c5c 100%);">
            <div class="row align-items-center" style="height:100%">
                <div class="col">
                    <div>
                        <button class="btn btn-primary" type="button" disabled>
                            <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
                            Prepare service...
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.webassembly.js"></script>
</body>

</html>

실행해보면 처음 접속시 아래와 같이 로딩 메세가 표시되다가 다운로드 후 렌더링이 완료되면 페이지가 표시가 됩니다.

.Net 7 Blazor WebAssembly App

Client 프로젝트의 wwwroot 폴더에 있는 index.html 파일의 내용입니다.
기본 템플릿으로 생성된 코드이며 .Net 6 로 생성된 기본 템플릿과 다르게 17 번째 라인부터 21 라인이 추가되어 있습니다.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>DotNet7BlazorWebAssembly</title>
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/app.css" rel="stylesheet" />
    <link rel="icon" type="image/png" href="favicon.png" />
    <link href="DotNet7BlazorWebAssembly.Client.styles.css" rel="stylesheet" />
</head>

<body>
    <div id="app">
        <svg class="loading-progress">
            <circle r="40%" cx="50%" cy="50%" />
            <circle r="40%" cx="50%" cy="50%" />
        </svg>
        <div class="loading-progress-text"></div>
    </div>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.webassembly.js"></script>
</body>

</html>

그리고, wwwroot\css\app.css 파일을 보시면 다음과 같이 추가된 css 코드를 확인할 수 있습니다.

.loading-progress {
    position: relative;
    display: block;
    width: 8rem;
    height: 8rem;
    margin: 20vh auto 1rem auto;
}

    .loading-progress circle {
        fill: none;
        stroke: #e0e0e0;
        stroke-width: 0.6rem;
        transform-origin: 50% 50%;
        transform: rotate(-90deg);
    }

        .loading-progress circle:last-child {
            stroke: #1b6ec2;
            stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
            transition: stroke-dasharray 0.05s ease-in-out;
        }

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-weight: bold;
    inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}

    .loading-progress-text:after {
        content: var(--blazor-load-percentage-text, "Loading");
    }

실행해보면 별도의 추가 코드 없이 처음 접속시 아래와 같이 진행율이 표시되다가 다운로드 후 렌더링이 완료되면 페이지가 표시가 됩니다.

.Net 8 Blazor Web App

Client 프로젝트의 Components 폴더에 있는 App.razor 파일의 내용입니다.
.Net 8 부터는 razor 구문으로 작성이 가능하게 변경되었습니다. 좋네요!
기본 템플릿으로 생성된 코드에서 RenderModeCurrent 변수를 추가해서
rendermode 를 지정하게 수정하고 PreRender 를 false 로 할당합니다.
(초기화 로직에 서버에서 다국어 관련 콘텐츠를 받아서 처리하는 부분을 포함한 서비스 특성상 미리 렌더링 되지 않게 하기 위함입니다.)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <base href="/" />
    <link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
    <link rel="stylesheet" href="app.css" />
    <link rel="stylesheet" href="DotNet8BlazorWebApp.styles.css" />
    <link rel="icon" type="image/png" href="favicon.png" />
    <HeadOutlet @rendermode="@RenderModeCurrent" />
</head>

<body>
    <div id="loadingInit" class="container-fluid"
         style="position:fixed;
             width: 100%;
             height: 100%;
             display: flex;
             align-items: center;
             justify-content: center;
             background-size: 400% 400%;
             background-image: linear-gradient(45deg, #24a3df 0%, #1430bd 25%, #8c2faf 50%, #e70c5c 100%);">
        <div class="row align-items-center" style="height:100%">
            <div class="col">
                <div>
                    <button class="btn btn-primary" type="button" disabled>
                        <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
                        Prepare service...
                    </button>
                </div>
            </div>
        </div>
    </div>
    <Routes @rendermode="@RenderModeCurrent" />
    <script src="_framework/blazor.web.js"></script>
    <script>
        function DeleteElementById(id) {
            var element = document.getElementById(id);
            element.parentNode.removeChild(element);
        };
    </script>
</body>

</html>
@code {
    InteractiveWebAssemblyRenderMode RenderModeCurrent => new InteractiveWebAssemblyRenderMode(false);
}

Server 프로젝트의 Routes.razor 파일의 내용입니다.
렌더링이 완료된 후 로딩 레이어를 삭제하는 Javascript function 을 호출합니다.

@inject IJSRuntime JS

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)" />
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
</Router>


@code {
    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JS.DeleteElementById("loadingInit");
        }
    }
}

실행해보면 처음 접속시 아래와 같이 로딩 메세가 표시되다가 다운로드 후 렌더링이 완료되면 페이지가 표시가 됩니다.

Github

해당 예제의 소스 코드는 다음 Github repository 를 참조하시면 됩니다.

Learn more on this topic

Related Blog Posts

Join in the conversation

Leave a Comment

0 Comments

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

무료 온라인 전광판

전광판

텍스트를 입력하고 텍스트 효과 및 배경효과 를 변경해서 전체화면으로 표시할 수 있는 전광판 용도로 사용하실 수 있습니다. 각종 스포츠 및 공연 관람시 응원 용도로 사용이 가능합니다.

Carousel

여러개의 슬라이드를 추가하여 프레젠테이션 및 이미지 슬라이드 용도로 사용하실 수 있습니다. 브라우저가 포함된 IT 기기로 큰 모니터에 연결하여 매장 내 공지사항 및 메뉴소개를 이미지로 표시할 수 있습니다.

Pin It on Pinterest

Shares
Share This

Share This

Share this post with your friends!

Shares