Note
호스트된 Blazor WebAssembly 솔루션은 계속 지원되지만 프로젝트 템플릿이 제거되어 .NET 8 이상에서 더 이상 지원되지 않습니다. 이 문서는 참조를 위해 .NET 7까지의 목차에 표시되지만 .NET 7은 더 이상 지원되지 않는 표준 지원 용어 릴리스입니다.
Warning
이 버전의 ASP.NET Core는 더 이상 지원되지 않습니다. 자세한 내용은 .NET 및 .NET Core 지원 정책을 참조하세요.
이 문서에서는 Razor 서버의 구성 요소 미리 렌더링을 포함하여 호스트된 Blazor WebAssembly 앱에 Razor 대한 구성 요소 통합 시나리오를 설명합니다.
Important
ASP.NET Core 릴리스의 프레임워크 변경으로 인해 이 문서의 다양한 지침 집합이 제공되었습니다. 이 문서의 지침을 사용하기 전에 이 문서의 맨 위에 있는 문서 버전 선택기가 앱에 사용하려는 ASP.NET Core 버전과 일치하는지 확인합니다.
미리 렌더링은 검색 엔진이 페이지 순위를 계산하는 데 사용할 수 있는 초기 HTTP 응답에 대한 콘텐츠를 렌더링하여 SEO(검색 엔진 최적화)를 향상시킬 수 있습니다.
솔루션 구성
미리 렌더링 구성
호스트 Blazor WebAssembly 된 앱에 대한 사전 렌더링을 설정하려면 다음을 수행합니다.
Blazor WebAssembly ASP.NET Core 앱에서 앱을 호스트합니다. 독립 실행형 Blazor WebAssembly 앱을 ASP.NET Core 솔루션에 추가하거나, 호스트된 옵션을 사용하여 Blazor WebAssembly 만든 호스트 Blazor WebAssembly 된 앱을 사용할 수 있습니다.
- Visual Studio: 추가 정보 대화 상자에서 앱을 만들 때 ASP.NET Core Hosted 확인란을 Blazor WebAssembly 선택합니다. 이 문서의 예제에서는 솔루션의 이름을 지정
BlazorHosted합니다. - Visual Studio Code/.NET CLI 명령 셸:
dotnet new blazorwasm -ho(옵션 사용-ho|--hosted). 이-o|--output {LOCATION}옵션을 사용하여 솔루션에 대한 폴더를 만들고 솔루션의 프로젝트 네임스페이스를 설정합니다. 이 문서의 예제에서 솔루션의 이름은BlazorHosted(dotnet new blazorwasm -ho -o BlazorHosted)입니다.
이 문서의 예제에서 호스트된 솔루션의 이름(어셈블리 이름)은 다음과 같습니다
BlazorHosted. 클라이언트 프로젝트의 네임스페이스는BlazorHosted.Client서버 프로젝트의 네임스페이스입니다BlazorHosted.Server.- Visual Studio: 추가 정보 대화 상자에서 앱을 만들 때 ASP.NET Core Hosted 확인란을 Blazor WebAssembly 선택합니다. 이 문서의 예제에서는 솔루션의 이름을 지정
프로젝트에서 파일을 삭제합니다
wwwroot/index.htmlBlazor WebAssembly.ClientClient 프로젝트에서 다음 줄을 삭제합니다.
Program.cs- builder.RootComponents.Add<App>("#app"); - builder.RootComponents.Add<HeadOutlet>("head::after");프로젝트의
_Host.cshtml폴더에 Server 파일을 추가Pages합니다. Visual Studio를 사용하거나 명령 셸의 명령과 함께 Blazor Server .NET CLI를 사용하여 템플릿에서dotnet new blazorserver -o BlazorServer만든 프로젝트에서 파일을 가져올 수 있습니다(-o BlazorServer이 옵션은 프로젝트에 대한 폴더를 만듭니다). 프로젝트의 Server 폴더에Pages파일을 배치한 후 파일을 다음과 같이 변경합니다._Host.cshtml파일에 다음 변경 내용을 적용합니다.Pages앱 페이지의 네임스페이스와 일치하도록 파일 맨 위에 있는 네임스페이 Server 스를 업데이트합니다.{APP NAMESPACE}다음 예제의 자리 표시자는 파일을 제공한_Host.cshtml기부자 앱 페이지의 네임스페이스를 나타냅니다.Delete:
- @namespace {APP NAMESPACE}.PagesAdd:
@namespace BlazorHosted.Server.Pages@using파일 맨 위에 프로젝트에 대한 Client 지시문을 추가합니다.@using BlazorHosted.ClientWebAssembly 프로젝트의 스타일시트를 가리키도록 스타일시트 링크를 업데이트합니다. 다음 예제에서 클라이언트 프로젝트의 네임스페이스는 .입니다
BlazorHosted.Client.{APP NAMESPACE}자리 표시자는 파일을 제공한_Host.cshtml기부자 앱의 네임스페이스를 나타냅니다. 구성 요소의 구성 요소 태그 도우미(<component>태그)HeadOutlet를 업데이트하여 구성 요소를 미리 렌더링합니다.Delete:
- <link href="css/site.css" rel="stylesheet" /> - <link href="{APP NAMESPACE}.styles.css" rel="stylesheet" /> - <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />Add:
<link href="css/app.css" rel="stylesheet" /> <link href="BlazorHosted.Client.styles.css" rel="stylesheet" /> <component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />Note
<link>부트스트랩 스타일시트(css/bootstrap/bootstrap.min.css)를 요청하는 요소를 그대로 둡니다.클라이언트 쪽 Blazor 스크립트를 Blazor WebAssembly 사용하도록 스크립트 원본을 업데이트합니다.
Delete:
- <script src="_framework/blazor.server.js"></script>Add:
<script src="_framework/blazor.webassembly.js"></script>다음을 사용하여
render-mode루트 구성 요소를 미리 렌더링하도록AppWebAssemblyPrerendered태그 도우미를 업데이트합니다.Delete:
- <component type="typeof(App)" render-mode="ServerPrerendered" />Add:
<component type="typeof(App)" render-mode="WebAssemblyPrerendered" />Important
사전 렌더링은 인증 엔드포인트(
/authentication/경로 세그먼트)에 대해 지원되지 않습니다. 자세한 내용은 ASP.NET Core Blazor WebAssembly 추가 보안 시나리오를 참조하세요.
Program.cs프로젝트 파일 Server 에서 대체 엔드포인트를index.html파일에서 페이지로_Host.cshtml변경합니다.Delete:
- app.MapFallbackToFile("index.html");Add:
app.MapFallbackToPage("/_Host");Client 및 Server 프로젝트가 미리 렌더링하는 동안 하나 이상의 일반적인 서비스를 사용하는 경우 서비스 등록을 두 프로젝트에서 호출할 수 있는 메서드로 팩터링합니다. 자세한 내용은 ASP.NET Core Blazor 종속성 주입을 참조하세요.
Server 프로젝트를 실행합니다. 호스트 Blazor WebAssembly 된 앱은 클라이언트용 프로젝트에서 미리 렌더링 Server 됩니다.
구성 요소를 페이지 또는 뷰에 포함하기 Razor 위한 구성
앱에서 RazorClient 서버 앱의 페이지 또는 뷰로 구성 요소를 포함하기 Blazor WebAssembly 위한 다음 섹션과 예제에는 추가 구성이 필요합니다.
프로젝트에는 Server 다음 파일과 폴더가 있어야 합니다.
Razor 페이지:
Pages/Shared/_Layout.cshtmlPages/Shared/_Layout.cshtml.cssPages/_ViewImports.cshtmlPages/_ViewStart.cshtml
MVC:
Views/Shared/_Layout.cshtmlViews/Shared/_Layout.cshtml.cssViews/_ViewImports.cshtmlViews/_ViewStart.cshtml
위의 파일은 다음을 사용하여 ASP.NET Core 프로젝트 템플릿에서 앱을 생성하여 가져올 수 있습니다.
- Visual Studio의 새 프로젝트 만들기 도구입니다.
- 명령 셸을 열고 (Pages) 또는
dotnet new webapp -o {PROJECT NAME}(MVC)를 실행합니다.Razordotnet new mvc -o {PROJECT NAME}자리 표시자에 대한 값이-o|--output있는 옵션은{PROJECT NAME}앱의 이름을 제공하고 앱의 폴더를 만듭니다.
가져온 _ViewImports.cshtml 파일의 네임스페이스를 파일을 받는 프로젝트에서 사용 중인 네임스페이 Server 스와 일치하도록 업데이트합니다.
Pages/_ViewImports.cshtml (Razor 페이지):
@using BlazorHosted.Server
@namespace BlazorHosted.Server.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Views/_ViewImports.cshtml (MVC):
@using BlazorHosted.Server
@using BlazorHosted.Server.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
가져온 레이아웃 파일( Pages/Shared/_Layout.cshtmlRazor Pages 또는 Views/Shared/_Layout.cshtml MVC용)을 업데이트합니다.
먼저 다음 예제에 있는 RPDonor.styles.css 기부자 프로젝트에서 제목과 스타일시트를 삭제합니다.
{PROJECT NAME} 자리 표시자는 기부자 프로젝트의 앱 이름을 나타냅니다.
- <title>@ViewData["Title"] - {PROJECT NAME}</title>
- <link rel="stylesheet" href="~/RPDonor.styles.css" asp-append-version="true" />
Client 레이아웃 파일에 프로젝트의 스타일을 포함합니다. 다음 예제 Client 에서 프로젝트의 네임스페이스는 .입니다 BlazorHosted.Client.
<title> 요소를 동시에 업데이트할 수 있습니다.
레이아웃 파일의 내용에 <head> 다음 줄을 배치합니다.
<title>@ViewData["Title"] - BlazorHosted</title>
<link href="css/app.css" rel="stylesheet" />
<link rel="stylesheet" href="BlazorHosted.Client.styles.css" asp-append-version="true" />
<component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />
가져온 레이아웃에는 두 Home 페이지와IndexPrivacy 탐색 링크가 포함됩니다. 링크가 호스트 Home 된 Blazor WebAssembly 앱을 가리키도록 하려면 하이퍼링크를 변경합니다.
- <a class="navbar-brand" asp-area="" asp-page="/Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
MVC 레이아웃 파일에서:
- <a class="navbar-brand" asp-area="" asp-controller="Home"
- asp-action="Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-controller="Home"
- asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
요소의 <footer> 앱 이름을 업데이트합니다. 다음 예제에서는 앱 이름을 BlazorHosted사용합니다.
- © {DATE} - {DONOR NAME} - <a asp-area="" asp-page="/Privacy">Privacy</a>
+ © {DATE} - BlazorHosted - <a asp-area="" asp-page="/Privacy">Privacy</a>
앞의 예제 {DATE} 에서 자리 표시자는 Pages 또는 MVC 프로젝트 템플릿에서 생성된 앱의 Razor 저작권 날짜를 나타냅니다.
Privacy 링크가 개인 정보 페이지(Razor Pages)로 이어지도록 하려면 Server 프로젝트에 개인 정보 페이지를 추가합니다.
Pages/Privacy.cshtml 프로젝트에서 다음을 수행 Server 합니다.
@page
@model PrivacyModel
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
MVC 기반 개인 정보 보기의 경우 Server 프로젝트에서 개인 정보 보기를 만듭니다.
View/Home/Privacy.cshtml 프로젝트에서 다음을 수행 Server 합니다.
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
Home MVC 앱의 컨트롤러에서 보기를 반환합니다.
다음 코드를 Controllers/HomeController.cs에 추가합니다.
public IActionResult Privacy()
{
return View();
}
기부자 앱에서 파일을 가져오는 경우 프로젝트의 네임스페이스(예Server: )와 일치하도록 파일의 BlazorHosted.Server 네임스페이스를 업데이트해야 합니다.
기부자 프로젝트의 Server 폴더에서 프로젝트로 wwwroot 정적 자산을 가져옵니다.
-
wwwroot/css폴더 및 콘텐츠 -
wwwroot/js폴더 및 콘텐츠 -
wwwroot/lib폴더 및 콘텐츠
ASP.NET Core 프로젝트 템플릿에서 기부자 프로젝트를 만들고 파일이 수정되지 않은 경우 기부자 프로젝트의 전체 wwwroot 폴더를 프로젝트로 Server 복사하고 아이콘 파일을 제거할 favicon 수 있습니다.
Warning
정적 자산을 폴더와 ClientServer 폴더 모두에 wwwroot 배치하지 않습니다. 두 폴더에 동일한 파일이 있는 경우 정적 자산이 동일한 웹 루트 경로를 공유하기 때문에 예외가 throw됩니다. 따라서 두 폴더가 아닌 두 폴더 중 wwwroot 하나에서 정적 자산을 호스트합니다.
이전 구성을 채택한 후 구성 요소를 프로젝트의 페이지 또는 뷰에 Razor 포함 Server 합니다. 이 문서의 다음 섹션에 있는 지침을 사용합니다.
- 구성 요소 태그 도우미를 사용하여 페이지 또는 보기에서 구성 요소 렌더링
- CSS 선택기를 사용하여 페이지 또는 보기에서 구성 요소 렌더링
구성 요소 태그 도우미를 사용하여 페이지 또는 보기에서 구성 요소 렌더링
추가 구성을 포함하여 솔루션을 구성한 후 구성 요소 태그 도우미는 페이지 또는 보기의 앱에서 Blazor WebAssembly 구성 요소를 렌더링하기 위한 두 가지 렌더링 모드를 지원합니다.
다음 Razor Pages 예제 Counter 에서는 구성 요소가 페이지에 렌더링됩니다. 구성 요소를 대화형으로 Blazor WebAssembly 만들기 위해 스크립트는 페이지의 렌더링 섹션에 포함됩니다.
Counter()와 함께 구성 요소에 {ASSEMBLY NAME}.Pages.Counter 대한 전체 네임스페이스를 사용하지 않도록 하려면 클라이언트 프로젝트의 @using 네임스페이스에 대한 지시문을 추가 Pages 합니다. 다음 예제 Client 에서 프로젝트의 네임스페이스는 .입니다 BlazorHosted.Client.
프로젝트에서 다음을 Server 수행 Pages/RazorPagesCounter1.cshtml합니다.
@page
@using BlazorHosted.Client.Pages
<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
Server 프로젝트를 실행합니다. 에서 Razor/razorpagescounter1페이지로 이동합니다. 미리 렌더링된 Counter 구성 요소가 페이지에 포함됩니다.
RenderMode는 구성 요소에 대해 다음을 구성합니다.
- 페이지에 미리 렌더링되었습니다.
- 페이지에 정적 HTML로 렌더링할지 여부 또는 사용자 에이전트에서 Blazor 앱을 부트스트랩하는 데 필요한 정보를 포함할지 여부
매개 변수 전달과 RenderMode 구성을 포함하여 구성 요소 태그 도우미에 대한 자세한 내용은 ASP.NET Core의 구성 요소 태그 도우미를 참조하세요.
구성 요소에서 사용하는 정적 리소스와 앱에서 레이아웃 페이지를 구성하는 방법에 따라 추가 작업이 필요할 수 있습니다. 일반적으로 스크립트는 페이지 또는 보기의 Scripts 렌더링 섹션에 추가되고 스타일시트는 레이아웃의 <head> 요소 콘텐츠에 추가됩니다.
렌더링 조각을 통해 자식 콘텐츠 설정
구성 요소 태그 도우미는 자식 콘텐츠(예RenderFragment: ) 지원하지 않습니다. 전달하려는 자식 콘텐츠로 렌더링하려는 구성 요소를 참조하는 구성 요소(Razor)를 만든 .razor 다음 페이지 또는 보기에서 구성 요소를 호출 Razor 하는 것이 좋습니다.
최상위 미리 렌더링된 구성 요소가 게시에서 잘려나가지 않는지 확인합니다.
구성 요소 태그 도우미가 게시 시 트리밍이 적용되는 라이브러리의 구성 요소를 직접 참조하는 경우 클라이언트 쪽 앱 코드에서 해당 구성 요소에 대한 참조가 없으므로 게시 중에 구성 요소가 잘려나갈 수 있습니다. 따라서 구성 요소가 미리 렌더링되지 않아 출력에 빈 자리가 남습니다. 이 경우 클라이언트 쪽 앱의 모든 클래스에 특성을 추가하여 DynamicDependency 라이브러리 구성 요소를 유지하도록 트리머에게 지시합니다. 호출 SomeLibraryComponentToBePreserved된 구성 요소를 유지하려면 모든 구성 요소에 다음을 추가합니다.
@using System.Diagnostics.CodeAnalysis
@attribute [DynamicDependency(DynamicallyAccessedMemberTypes.All,
typeof(SomeLibraryComponentToBePreserved))]
앱은 일반적으로 구성 요소(트리밍되지 않음)를 미리 생성하기 때문에 이전 접근 방식이 필요하지 않습니다. 이 경우 라이브러리에서 구성 요소를 참조합니다(트리밍되지 않음). 라이브러리를 트리밍할 수 있는 경우에만 라이브러리 구성 요소를 직접 미리 렌더링하는 데 명시적으로 사용합니다 DynamicDependency .
CSS 선택기를 사용하여 페이지 또는 보기에서 구성 요소 렌더링
추가 구성을 포함하여 솔루션을 구성한 후 파일의 호스트된 Client 솔루션 Blazor WebAssembly 프로젝트에 루트 구성 요소를 추가합니다Program.cs. 다음 예제 Counter 에서 구성 요소는 일치하는 id요소를 선택하는 CSS 선택기를 사용하여 루트 구성 요소로 counter-component 선언됩니다. 다음 예제 Client 에서 프로젝트의 네임스페이스는 .입니다 BlazorHosted.Client.
프로젝트 파일 Program.cs 에서 Client 프로젝트 구성 요소의 Razor 네임스페이스를 파일 맨 위에 추가합니다.
using BlazorHosted.Client.Pages;
구성 builder 요소가 설정된 Program.cs후 구성 요소를 루트 구성 요소로 추가 Counter 합니다.
builder.RootComponents.Add<Counter>("#counter-component");
다음 Razor Pages 예제 Counter 에서는 구성 요소가 페이지에 렌더링됩니다. 구성 요소를 대화형으로 Blazor WebAssembly 만들기 위해 스크립트는 페이지의 렌더링 섹션에 포함됩니다.
프로젝트에서 다음을 Server 수행 Pages/RazorPagesCounter2.cshtml합니다.
@page
<div id="counter-component">Loading...</div>
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
Server 프로젝트를 실행합니다. 에서 Razor/razorpagescounter2페이지로 이동합니다. 미리 렌더링된 Counter 구성 요소가 페이지에 포함됩니다.
구성 요소에서 사용하는 정적 리소스와 앱에서 레이아웃 페이지를 구성하는 방법에 따라 추가 작업이 필요할 수 있습니다. 일반적으로 스크립트는 페이지 또는 보기의 Scripts 렌더링 섹션에 추가되고 스타일시트는 레이아웃의 <head> 요소 콘텐츠에 추가됩니다.
Note
앞의 예제에서는 앱이 미리 렌더링되고 CSS 선택기를 사용하여 JSException Pages 또는 MVC 앱에 Blazor WebAssembly 통합된 경우 Razor 를 throw 합니다. 프로젝트의 Client 구성 요소 중 Razor 하나로 이동하거나 포함된 구성 요소가 있는 페이지 또는 보기 Server 로 이동하면 하나 이상이 JSExceptionthrow됩니다.
이는 라우팅 가능한 Blazor WebAssembly 구성 요소와 앱을 미리 렌더링하고 통합하는 Razor 것이 CSS 선택기 사용과 호환되지 않으므로 일반적인 동작입니다.
이전 섹션의 예제를 사용했으며 샘플 앱에서 CSS 선택기 작업을 확인하려는 경우 프로젝트 App 파일의 Client 루트 구성 요소 사양을 Program.cs 주석으로 처리합니다.
- builder.RootComponents.Add<App>("#app");
+ //builder.RootComponents.Add<App>("#app");
CSS 선택기를 사용하는 포함된 Razor 구성 요소를 사용하여 페이지 또는 보기로 이동합니다(예 /razorpagescounter2 : 앞의 예제). 페이지 또는 뷰는 포함된 구성 요소와 함께 로드되고 포함된 구성 요소는 예상대로 작동합니다.
미리 렌더링된 상태 유지
미리 렌더링된 상태를 유지하지 않으면 미리 렌더링하는 동안 사용된 상태를 잃게 되며 앱이 완전히 로드되면 다시 만들어야 합니다. 상태가 비동기적으로 설정된 경우 미리 렌더링된 UI가 임시 자리 표시자로 대체된 다음, 완전히 다시 렌더링되면 UI가 깜박일 수 있습니다.
미리 렌더링된 구성 요소의 상태를 유지하려면 지속 구성 요소 상태 태그 도우미(참조 원본)를 사용합니다. 태그 도우미의 태그 <persist-component-state />를 구성 요소를 미리 렌더링하는 앱의 </body> 페이지 내 닫는 _Host 태그 안에 추가합니다.
Note
문서 링크는 .NET 참조 소스를 가리키며, 일반적으로 저장소의 기본 브랜치를 로드합니다. 이는 .NET의 다음 릴리스를 위한 현재 개발 상태를 나타냅니다. 특정 릴리스를 위한 태그를 선택하려면 Switch branches or tags 드롭다운 목록을 사용하세요. 자세한 내용은 ASP.NET Core 소스 코드(dotnet/AspNetCore.Docs #26205)의 버전 태그를 선택하는 방법을 참조하세요.
Pages/_Host.cshtml
Blazor WebAssembly가 호스트 WebAssemblyPrerendered 된 앱에서 미리 렌더링된(Blazor WebAssembly) 앱의 경우:
<body>
...
<persist-component-state />
</body>
PersistentComponentState 서비스를 사용하여 유지할 상태를 결정합니다. PersistentComponentState.RegisterOnPersisting은 앱이 일시 중지되기 전에 구성 요소 상태를 유지하도록 콜백을 등록합니다. 애플리케이션이 다시 시작될 때 상태가 검색됩니다. 앱 종료 중에 잠재적인 경합 상태를 방지하기 위해 초기화 코드가 끝날 때 호출합니다.
다음 예제에서
-
{TYPE}자리 표시자는 유지할 데이터 형식을 나타냅니다(예:WeatherForecast[]). -
{TOKEN}자리 표시자는 상태 식별자 문자열입니다(예:fetchdata).
@implements IDisposable
@inject PersistentComponentState ApplicationState
...
@code {
private {TYPE} data;
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
if (!ApplicationState.TryTakeFromJson<{TYPE}>(
"{TOKEN}", out var restored))
{
data = await ...;
}
else
{
data = restored!;
}
// Call at the end to avoid a potential race condition at app shutdown
persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
}
private Task PersistData()
{
ApplicationState.PersistAsJson("{TOKEN}", data);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
다음 예제는 프로젝트 템플릿을 기반으로 FetchData 호스트 Blazor WebAssembly 된 앱에서 구성 요소의 Blazor 업데이트된 버전입니다.
WeatherForecastPreserveState 구성 요소는 미리 렌더링하는 동안 날씨 예측 상태를 유지한 다음, 상태를 검색하여 구성 요소를 초기화합니다.
구성 요소 상태 유지 태그 도우미는 모든 구성 요소 호출 후 구성 요소 상태를 유지합니다.
Pages/WeatherForecastPreserveState.razor:
@page "/weather-forecast-preserve-state"
@using BlazorSample.Shared
@implements IDisposable
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState
<PageTitle>Weather Forecast</PageTitle>
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
nameof(forecasts), out var restored))
{
forecasts = await WeatherForecastService.GetForecastAsync(
DateOnly.FromDateTime(DateTime.Now));
}
else
{
forecasts = restored!;
}
// Call at the end to avoid a potential race condition at app shutdown
persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
}
private Task PersistData()
{
ApplicationState.PersistAsJson(nameof(forecasts), forecasts);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
미리 렌더링하는 동안 사용된 것과 동일한 상태로 구성 요소를 초기화하면 비용이 많이 드는 초기화 단계가 한 번만 실행됩니다. 렌더링된 UI도 미리 렌더링된 UI와 일치하므로 브라우저에서 깜박임이 발생하지 않습니다.
지속형 미리 렌더링된 상태는 구성 요소 상태를 복원하는 데 사용되는 클라이언트로 전송됩니다. 호스트 Blazor WebAssembly 된 앱에서 미리 렌더링하기 위해 데이터는 브라우저에 노출되며 중요한 개인 정보를 포함해서는 안됩니다.
추가 Blazor WebAssembly 리소스
- 어셈블리 지연 로드를 사용한 미리 렌더링 지원
-
Razor 미리 렌더링과 관련된 구성 요소 수명 주기 주제
-
구성 요소 초기화(
OnInitialized{Async}) -
구성 요소 렌더링 후(
OnAfterRender{Async}) - 미리 렌더링한 후 상태 저장 다시 연결: 섹션의 콘텐츠가 중점 Blazor Server 적이고 상태 저장 SignalR다시 연결이지만 호스트 Blazor WebAssembly 된 앱(WebAssemblyPrerendered)에서 미리 렌더링하는 시나리오에는 개발자 코드가 두 번 실행되지 않도록 하는 유사한 조건과 접근 방식이 포함됩니다. 미리 렌더링하는 동안 초기화 코드를 실행하는 동안 상태를 유지하려면 이 문서의 미리 렌더링된 상태 유지 섹션을 참조하세요.
- JavaScript interop을 사용한 미리 렌더링
-
구성 요소 초기화(
- 사전 렌더링과 관련된 인증 및 권한 부여 주체
- ASP.NET Core Blazor WebAssembly 호스트 및 배포
- 오류 처리: 미리 렌더링
-
OnNavigateAsync은 미리 렌더링할 때 두 번 실행됩니다:
OnNavigateAsync을(를) 사용하여 비동기 탐색 이벤트를 처리합니다
미리 렌더링은 검색 엔진이 페이지 순위를 계산하는 데 사용할 수 있는 초기 HTTP 응답에 대한 콘텐츠를 렌더링하여 SEO(검색 엔진 최적화)를 향상시킬 수 있습니다.
솔루션 구성
미리 렌더링 구성
호스트 Blazor WebAssembly 된 앱에 대한 사전 렌더링을 설정하려면 다음을 수행합니다.
Blazor WebAssembly ASP.NET Core 앱에서 앱을 호스트합니다. 독립 실행형 Blazor WebAssembly 앱을 ASP.NET Core 솔루션에 추가하거나, 호스트된 옵션을 사용하여 Blazor WebAssembly 만든 호스트 Blazor WebAssembly 된 앱을 사용할 수 있습니다.
- Visual Studio: 추가 정보 대화 상자에서 앱을 만들 때 ASP.NET Core Hosted 확인란을 Blazor WebAssembly 선택합니다. 이 문서의 예제에서는 솔루션의 이름을 지정
BlazorHosted합니다. - Visual Studio Code/.NET CLI 명령 셸:
dotnet new blazorwasm -ho(옵션 사용-ho|--hosted). 이-o|--output {LOCATION}옵션을 사용하여 솔루션에 대한 폴더를 만들고 솔루션의 프로젝트 네임스페이스를 설정합니다. 이 문서의 예제에서 솔루션의 이름은BlazorHosted(dotnet new blazorwasm -ho -o BlazorHosted)입니다.
이 문서의 예제에서 클라이언트 프로젝트의 네임스페이스는
BlazorHosted.Client서버 프로젝트의 네임스페이스입니다BlazorHosted.Server.- Visual Studio: 추가 정보 대화 상자에서 앱을 만들 때 ASP.NET Core Hosted 확인란을 Blazor WebAssembly 선택합니다. 이 문서의 예제에서는 솔루션의 이름을 지정
프로젝트에서 파일을 삭제합니다
wwwroot/index.htmlBlazor WebAssembly.ClientClient 프로젝트에서 다음 줄을 삭제합니다.
Program.cs- builder.RootComponents.Add<App>("#app"); - builder.RootComponents.Add<HeadOutlet>("head::after");_Host.cshtml프로젝트_Layout.cshtml폴더에 Server 파일을 추가하고Pages추가합니다. Visual Studio를 사용하거나 명령 셸의 명령과 함께 Blazor Server .NET CLI를 사용하여 템플릿에서dotnet new blazorserver -o BlazorServer만든 프로젝트에서 파일을 가져올 수 있습니다(-o BlazorServer이 옵션은 프로젝트에 대한 폴더를 만듭니다). 프로젝트의 Server 폴더에Pages파일을 배치한 후 파일을 다음과 같이 변경합니다.Important
페이지의 제목(
_Layout.cshtml구성 요소) 및 기타 헤드 요소( 구성 요소)와 같은 HeadOutlet 콘텐츠를 제어하려면<head>구성 요소에 대해 PageTitle와 함께 레이아웃 페이지(HeadContent)를 사용해야 합니다. 자세한 내용은 ASP.NET Core Blazor 앱의 헤드 콘텐츠 제어를 참조하세요._Layout.cshtml파일에 다음 변경 내용을 적용합니다.Pages앱 페이지의 네임스페이스와 일치하도록 파일 맨 위에 있는 네임스페이 Server 스를 업데이트합니다.{APP NAMESPACE}다음 예제의 자리 표시자는 파일을 제공한_Layout.cshtml기부자 앱 페이지의 네임스페이스를 나타냅니다.Delete:
- @namespace {APP NAMESPACE}.PagesAdd:
@namespace BlazorHosted.Server.Pages@using파일 맨 위에 프로젝트에 대한 Client 지시문을 추가합니다.@using BlazorHosted.ClientWebAssembly 프로젝트의 스타일시트를 가리키도록 스타일시트 링크를 업데이트합니다. 다음 예제에서 클라이언트 프로젝트의 네임스페이스는 .입니다
BlazorHosted.Client.{APP NAMESPACE}자리 표시자는 파일을 제공한_Layout.cshtml기부자 앱의 네임스페이스를 나타냅니다. 구성 요소의 구성 요소 태그 도우미(<component>태그)HeadOutlet를 업데이트하여 구성 요소를 미리 렌더링합니다.Delete:
- <link href="css/site.css" rel="stylesheet" /> - <link href="{APP NAMESPACE}.styles.css" rel="stylesheet" /> - <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />Add:
<link href="css/app.css" rel="stylesheet" /> <link href="BlazorHosted.Client.styles.css" rel="stylesheet" /> <component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />Note
<link>부트스트랩 스타일시트(css/bootstrap/bootstrap.min.css)를 요청하는 요소를 그대로 둡니다.클라이언트 쪽 Blazor 스크립트를 Blazor WebAssembly 사용하도록 스크립트 원본을 업데이트합니다.
Delete:
- <script src="_framework/blazor.server.js"></script>Add:
<script src="_framework/blazor.webassembly.js"></script>
_Host.cshtml파일에서:네임스페이
Pages스를 프로젝트의 네임스페이스로 변경합니다 Client .{APP NAMESPACE}자리 표시자는 파일을 제공한_Host.cshtml기부자 앱 페이지의 네임스페이스를 나타냅니다.Delete:
- @namespace {APP NAMESPACE}.PagesAdd:
@namespace BlazorHosted.Client다음을 사용하여
render-mode루트 구성 요소를 미리 렌더링하도록AppWebAssemblyPrerendered태그 도우미를 업데이트합니다.Delete:
- <component type="typeof(App)" render-mode="ServerPrerendered" />Add:
<component type="typeof(App)" render-mode="WebAssemblyPrerendered" />Important
사전 렌더링은 인증 엔드포인트(
/authentication/경로 세그먼트)에 대해 지원되지 않습니다. 자세한 내용은 ASP.NET Core Blazor WebAssembly 추가 보안 시나리오를 참조하세요.
프로젝트의 엔드포인트 매핑 Server 에서
Program.cs파일에서index.html페이지로_Host.cshtml대체를 변경합니다.Delete:
- app.MapFallbackToFile("index.html");Add:
app.MapFallbackToPage("/_Host");Client 및 Server 프로젝트가 미리 렌더링하는 동안 하나 이상의 일반적인 서비스를 사용하는 경우 서비스 등록을 두 프로젝트에서 호출할 수 있는 메서드로 팩터링합니다. 자세한 내용은 ASP.NET Core Blazor 종속성 주입을 참조하세요.
Server 프로젝트를 실행합니다. 호스트 Blazor WebAssembly 된 앱은 클라이언트용 프로젝트에서 미리 렌더링 Server 됩니다.
구성 요소를 페이지 또는 뷰에 포함하기 Razor 위한 구성
앱에서 RazorClient 서버 앱의 페이지 또는 뷰로 구성 요소를 포함하기 Blazor WebAssembly 위한 다음 섹션과 예제에는 추가 구성이 필요합니다.
프로젝트에는 Server 다음 파일과 폴더가 있어야 합니다.
Razor 페이지:
Pages/Shared/_Layout.cshtmlPages/Shared/_Layout.cshtml.cssPages/_ViewImports.cshtmlPages/_ViewStart.cshtml
MVC:
Views/Shared/_Layout.cshtmlViews/Shared/_Layout.cshtml.cssViews/_ViewImports.cshtmlViews/_ViewStart.cshtml
Important
페이지의 제목(_Layout.cshtml 구성 요소) 및 기타 헤드 요소( 구성 요소)와 같은 HeadOutlet 콘텐츠를 제어하려면 <head> 구성 요소에 대해 PageTitle와 함께 레이아웃 페이지(HeadContent)를 사용해야 합니다. 자세한 내용은 ASP.NET Core Blazor 앱의 헤드 콘텐츠 제어를 참조하세요.
위의 파일은 다음을 사용하여 ASP.NET Core 프로젝트 템플릿에서 앱을 생성하여 가져올 수 있습니다.
- Visual Studio의 새 프로젝트 만들기 도구입니다.
- 명령 셸을 열고 (Pages) 또는
dotnet new webapp -o {PROJECT NAME}(MVC)를 실행합니다.Razordotnet new mvc -o {PROJECT NAME}자리 표시자에 대한 값이-o|--output있는 옵션은{PROJECT NAME}앱의 이름을 제공하고 앱의 폴더를 만듭니다.
가져온 _ViewImports.cshtml 파일의 네임스페이스를 파일을 받는 프로젝트에서 사용 중인 네임스페이 Server 스와 일치하도록 업데이트합니다.
Pages/_ViewImports.cshtml (Razor 페이지):
@using BlazorHosted.Server
@namespace BlazorHosted.Server.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Views/_ViewImports.cshtml (MVC):
@using BlazorHosted.Server
@using BlazorHosted.Server.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
가져온 레이아웃 파일( Pages/Shared/_Layout.cshtmlRazor Pages 또는 Views/Shared/_Layout.cshtml MVC용)을 업데이트합니다.
먼저 다음 예제에 있는 RPDonor.styles.css 기부자 프로젝트에서 제목과 스타일시트를 삭제합니다.
{PROJECT NAME} 자리 표시자는 기부자 프로젝트의 앱 이름을 나타냅니다.
- <title>@ViewData["Title"] - {PROJECT NAME}</title>
- <link rel="stylesheet" href="~/RPDonor.styles.css" asp-append-version="true" />
Client 레이아웃 파일에 프로젝트의 스타일을 포함합니다. 다음 예제 Client 에서 프로젝트의 네임스페이스는 .입니다 BlazorHosted.Client.
<title> 요소를 동시에 업데이트할 수 있습니다.
레이아웃 파일의 내용에 <head> 다음 줄을 배치합니다.
<title>@ViewData["Title"] - BlazorHosted</title>
<link href="css/app.css" rel="stylesheet" />
<link rel="stylesheet" href="BlazorHosted.Client.styles.css" asp-append-version="true" />
<component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />
가져온 레이아웃에는 두 Home 페이지와IndexPrivacy 탐색 링크가 포함됩니다. 링크가 호스트 Home 된 Blazor WebAssembly 앱을 가리키도록 하려면 하이퍼링크를 변경합니다.
- <a class="navbar-brand" asp-area="" asp-page="/Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
MVC 레이아웃 파일에서:
- <a class="navbar-brand" asp-area="" asp-controller="Home"
- asp-action="Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-controller="Home"
- asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
요소의 <footer> 앱 이름을 업데이트합니다. 다음 예제에서는 앱 이름을 BlazorHosted사용합니다.
- © {DATE} - {DONOR NAME} - <a asp-area="" asp-page="/Privacy">Privacy</a>
+ © {DATE} - BlazorHosted - <a asp-area="" asp-page="/Privacy">Privacy</a>
앞의 예제 {DATE} 에서 자리 표시자는 Pages 또는 MVC 프로젝트 템플릿에서 생성된 앱의 Razor 저작권 날짜를 나타냅니다.
Privacy 링크가 개인 정보 페이지(Razor Pages)로 이어지도록 하려면 Server 프로젝트에 개인 정보 페이지를 추가합니다.
Pages/Privacy.cshtml 프로젝트에서 다음을 수행 Server 합니다.
@page
@model PrivacyModel
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
MVC 기반 개인 정보 보기의 경우 Server 프로젝트에서 개인 정보 보기를 만듭니다.
View/Home/Privacy.cshtml 프로젝트에서 다음을 수행 Server 합니다.
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
Home MVC 앱의 컨트롤러에서 보기를 반환합니다.
다음 코드를 Controllers/HomeController.cs에 추가합니다.
public IActionResult Privacy()
{
return View();
}
기부자 앱에서 파일을 가져오는 경우 프로젝트의 네임스페이스(예Server: )와 일치하도록 파일의 BlazorHosted.Server 네임스페이스를 업데이트해야 합니다.
기부자 프로젝트의 Server 폴더에서 프로젝트로 wwwroot 정적 자산을 가져옵니다.
-
wwwroot/css폴더 및 콘텐츠 -
wwwroot/js폴더 및 콘텐츠 -
wwwroot/lib폴더 및 콘텐츠
ASP.NET Core 프로젝트 템플릿에서 기부자 프로젝트를 만들고 파일이 수정되지 않은 경우 기부자 프로젝트의 전체 wwwroot 폴더를 프로젝트로 Server 복사하고 아이콘 파일을 제거할 favicon 수 있습니다.
Warning
정적 자산을 폴더와 ClientServer 폴더 모두에 wwwroot 배치하지 않습니다. 두 폴더에 동일한 파일이 있는 경우 각 폴더의 정적 자산이 동일한 웹 루트 경로를 공유하므로 예외가 throw됩니다. 따라서 두 폴더가 아닌 두 폴더에 wwwroot 정적 자산을 호스트합니다.
이전 구성을 채택한 후 구성 요소를 프로젝트의 페이지 또는 뷰에 Razor 포함 Server 합니다. 이 문서의 다음 섹션에 있는 지침을 사용합니다.
- 구성 요소 태그 도우미를 사용하여 페이지 또는 보기에서 구성 요소 렌더링
- CSS 선택기를 사용하여 페이지 또는 보기에서 구성 요소 렌더링
구성 요소 태그 도우미를 사용하여 페이지 또는 보기에서 구성 요소 렌더링
추가 구성을 포함하여 솔루션을 구성한 후 구성 요소 태그 도우미는 페이지 또는 보기의 앱에서 Blazor WebAssembly 구성 요소를 렌더링하기 위한 두 가지 렌더링 모드를 지원합니다.
다음 Razor Pages 예제 Counter 에서는 구성 요소가 페이지에 렌더링됩니다. 구성 요소를 대화형으로 Blazor WebAssembly 만들기 위해 스크립트는 페이지의 렌더링 섹션에 포함됩니다.
Counter()와 함께 구성 요소에 {ASSEMBLY NAME}.Pages.Counter 대한 전체 네임스페이스를 사용하지 않도록 하려면 클라이언트 프로젝트의 @using 네임스페이스에 대한 지시문을 추가 Pages 합니다. 다음 예제 Client 에서 프로젝트의 네임스페이스는 .입니다 BlazorHosted.Client.
프로젝트에서 다음을 Server 수행 Pages/RazorPagesCounter1.cshtml합니다.
@page
@using BlazorHosted.Client.Pages
<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
Server 프로젝트를 실행합니다. 에서 Razor/razorpagescounter1페이지로 이동합니다. 미리 렌더링된 Counter 구성 요소가 페이지에 포함됩니다.
RenderMode는 구성 요소에 대해 다음을 구성합니다.
- 페이지에 미리 렌더링되었습니다.
- 페이지에 정적 HTML로 렌더링할지 여부 또는 사용자 에이전트에서 Blazor 앱을 부트스트랩하는 데 필요한 정보를 포함할지 여부
매개 변수 전달과 RenderMode 구성을 포함하여 구성 요소 태그 도우미에 대한 자세한 내용은 ASP.NET Core의 구성 요소 태그 도우미를 참조하세요.
구성 요소에서 사용하는 정적 리소스와 앱에서 레이아웃 페이지를 구성하는 방법에 따라 추가 작업이 필요할 수 있습니다. 일반적으로 스크립트는 페이지 또는 보기의 Scripts 렌더링 섹션에 추가되고 스타일시트는 레이아웃의 <head> 요소 콘텐츠에 추가됩니다.
렌더링 조각을 통해 자식 콘텐츠 설정
구성 요소 태그 도우미는 자식 콘텐츠(예RenderFragment: ) 지원하지 않습니다. 전달하려는 자식 콘텐츠로 렌더링하려는 구성 요소를 참조하는 구성 요소(Razor)를 만든 .razor 다음 페이지 또는 보기에서 구성 요소를 호출 Razor 하는 것이 좋습니다.
최상위 미리 렌더링된 구성 요소가 게시에서 잘려나가지 않는지 확인합니다.
구성 요소 태그 도우미가 게시 시 트리밍이 적용되는 라이브러리의 구성 요소를 직접 참조하는 경우 클라이언트 쪽 앱 코드에서 해당 구성 요소에 대한 참조가 없으므로 게시 중에 구성 요소가 잘려나갈 수 있습니다. 따라서 구성 요소가 미리 렌더링되지 않아 출력에 빈 자리가 남습니다. 이 경우 클라이언트 쪽 앱의 모든 클래스에 특성을 추가하여 DynamicDependency 라이브러리 구성 요소를 유지하도록 트리머에게 지시합니다. 호출 SomeLibraryComponentToBePreserved된 구성 요소를 유지하려면 모든 구성 요소에 다음을 추가합니다.
@using System.Diagnostics.CodeAnalysis
@attribute [DynamicDependency(DynamicallyAccessedMemberTypes.All,
typeof(SomeLibraryComponentToBePreserved))]
앱은 일반적으로 구성 요소(트리밍되지 않음)를 미리 생성하기 때문에 이전 접근 방식이 필요하지 않습니다. 이 경우 라이브러리에서 구성 요소를 참조합니다(트리밍되지 않음). 라이브러리를 트리밍할 수 있는 경우에만 라이브러리 구성 요소를 직접 미리 렌더링하는 데 명시적으로 사용합니다 DynamicDependency .
CSS 선택기를 사용하여 페이지 또는 보기에서 구성 요소 렌더링
추가 구성을 포함하여 솔루션을 구성한 후 파일의 호스트된 Client 솔루션 Blazor WebAssembly 프로젝트에 루트 구성 요소를 추가합니다Program.cs. 다음 예제 Counter 에서 구성 요소는 일치하는 id요소를 선택하는 CSS 선택기를 사용하여 루트 구성 요소로 counter-component 선언됩니다. 다음 예제 Client 에서 프로젝트의 네임스페이스는 .입니다 BlazorHosted.Client.
프로젝트 파일 Program.cs 에서 Client 프로젝트 구성 요소의 Razor 네임스페이스를 파일 맨 위에 추가합니다.
using BlazorHosted.Client.Pages;
구성 builder 요소가 설정된 Program.cs후 구성 요소를 루트 구성 요소로 추가 Counter 합니다.
builder.RootComponents.Add<Counter>("#counter-component");
다음 Razor Pages 예제 Counter 에서는 구성 요소가 페이지에 렌더링됩니다. 구성 요소를 대화형으로 Blazor WebAssembly 만들기 위해 스크립트는 페이지의 렌더링 섹션에 포함됩니다.
프로젝트에서 다음을 Server 수행 Pages/RazorPagesCounter2.cshtml합니다.
@page
<div id="counter-component">Loading...</div>
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
Server 프로젝트를 실행합니다. 에서 Razor/razorpagescounter2페이지로 이동합니다. 미리 렌더링된 Counter 구성 요소가 페이지에 포함됩니다.
구성 요소에서 사용하는 정적 리소스와 앱에서 레이아웃 페이지를 구성하는 방법에 따라 추가 작업이 필요할 수 있습니다. 일반적으로 스크립트는 페이지 또는 보기의 Scripts 렌더링 섹션에 추가되고 스타일시트는 레이아웃의 <head> 요소 콘텐츠에 추가됩니다.
Note
앞의 예제에서는 앱이 미리 렌더링되고 CSS 선택기를 사용하여 JSException Pages 또는 MVC 앱에 Blazor WebAssembly 통합된 경우 Razor 를 throw 합니다. 프로젝트의 Client 구성 요소 중 Razor 하나로 이동하거나 포함된 구성 요소가 있는 페이지 또는 보기 Server 로 이동하면 하나 이상이 JSExceptionthrow됩니다.
이는 라우팅 가능한 Blazor WebAssembly 구성 요소와 앱을 미리 렌더링하고 통합하는 Razor 것이 CSS 선택기 사용과 호환되지 않으므로 일반적인 동작입니다.
이전 섹션의 예제를 사용했으며 샘플 앱에서 CSS 선택기 작업을 확인하려는 경우 프로젝트 App 파일의 Client 루트 구성 요소 사양을 Program.cs 주석으로 처리합니다.
- builder.RootComponents.Add<App>("#app");
+ //builder.RootComponents.Add<App>("#app");
CSS 선택기를 사용하는 포함된 Razor 구성 요소를 사용하여 페이지 또는 보기로 이동합니다(예 /razorpagescounter2 : 앞의 예제). 페이지 또는 뷰는 포함된 구성 요소와 함께 로드되고 포함된 구성 요소는 예상대로 작동합니다.
미리 렌더링된 상태 유지
미리 렌더링된 상태를 유지하지 않으면 미리 렌더링하는 동안 사용된 상태를 잃게 되며 앱이 완전히 로드되면 다시 만들어야 합니다. 상태가 비동기적으로 설정된 경우 미리 렌더링된 UI가 임시 자리 표시자로 대체된 다음, 완전히 다시 렌더링되면 UI가 깜박일 수 있습니다.
이러한 문제를 해결하기 위해 Blazor는 구성 요소 상태 유지 태그 도우미를 사용하여 미리 렌더링된 페이지에서 상태 유지를 지원합니다. 닫는 <persist-component-state /> 태그 안에 태그 도우미 태그인 </body>를 추가합니다.
Pages/_Layout.cshtml:
<body>
...
<persist-component-state />
</body>
PersistentComponentState 서비스를 사용하여 유지할 상태를 결정합니다. PersistentComponentState.RegisterOnPersisting은 앱이 일시 중지되기 전에 구성 요소 상태를 유지하도록 콜백을 등록합니다. 애플리케이션이 다시 시작될 때 상태가 검색됩니다. 앱 종료 중에 잠재적인 경합 상태를 방지하기 위해 초기화 코드가 끝날 때 호출합니다.
다음 예제는 프로젝트 템플릿을 기반으로 FetchData 호스트 Blazor WebAssembly 된 앱에서 구성 요소의 Blazor 업데이트된 버전입니다.
WeatherForecastPreserveState 구성 요소는 미리 렌더링하는 동안 날씨 예측 상태를 유지한 다음, 상태를 검색하여 구성 요소를 초기화합니다.
구성 요소 상태 유지 태그 도우미는 모든 구성 요소 호출 후 구성 요소 상태를 유지합니다.
Pages/WeatherForecastPreserveState.razor:
@page "/weather-forecast-preserve-state"
@implements IDisposable
@using BlazorSample.Shared
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState
<PageTitle>Weather Forecast</PageTitle>
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
nameof(forecasts), out var restored))
{
forecasts =
await WeatherForecastService.GetForecastAsync(DateTime.Now);
}
else
{
forecasts = restored!;
}
// Call at the end to avoid a potential race condition at app shutdown
persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
}
private Task PersistData()
{
ApplicationState.PersistAsJson(nameof(forecasts), forecasts);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
미리 렌더링하는 동안 사용된 것과 동일한 상태로 구성 요소를 초기화하면 비용이 많이 드는 초기화 단계가 한 번만 실행됩니다. 렌더링된 UI도 미리 렌더링된 UI와 일치하므로 브라우저에서 깜박임이 발생하지 않습니다.
지속형 미리 렌더링된 상태는 구성 요소 상태를 복원하는 데 사용되는 클라이언트로 전송됩니다. 호스트 Blazor WebAssembly 된 앱에서 미리 렌더링하기 위해 데이터는 브라우저에 노출되며 중요한 개인 정보를 포함해서는 안됩니다.
추가 Blazor WebAssembly 리소스
- 어셈블리 지연 로드를 사용한 미리 렌더링 지원
-
Razor 미리 렌더링과 관련된 구성 요소 수명 주기 주제
-
구성 요소 초기화(
OnInitialized{Async}) -
구성 요소 렌더링 후(
OnAfterRender{Async}) - 미리 렌더링한 후 상태 저장 다시 연결: 섹션의 콘텐츠가 중점 Blazor Server 적이고 상태 저장 SignalR다시 연결이지만 호스트 Blazor WebAssembly 된 앱(WebAssemblyPrerendered)에서 미리 렌더링하는 시나리오에는 개발자 코드가 두 번 실행되지 않도록 하는 유사한 조건과 접근 방식이 포함됩니다. 미리 렌더링하는 동안 초기화 코드를 실행하는 동안 상태를 유지하려면 이 문서의 미리 렌더링된 상태 유지 섹션을 참조하세요.
- JavaScript interop을 사용한 미리 렌더링
-
구성 요소 초기화(
- 사전 렌더링과 관련된 인증 및 권한 부여 주체
- ASP.NET Core Blazor WebAssembly 호스트 및 배포
미리 렌더링은 검색 엔진이 페이지 순위를 계산하는 데 사용할 수 있는 초기 HTTP 응답에 대한 콘텐츠를 렌더링하여 SEO(검색 엔진 최적화)를 향상시킬 수 있습니다.
솔루션 구성
미리 렌더링 구성
호스트 Blazor WebAssembly 된 앱에 대한 사전 렌더링을 설정하려면 다음을 수행합니다.
Blazor WebAssembly ASP.NET Core 앱에서 앱을 호스트합니다. 독립 실행형 Blazor WebAssembly 앱을 ASP.NET Core 솔루션에 추가하거나, 호스트된 옵션을 사용하여 Blazor WebAssembly 만든 호스트 Blazor WebAssembly 된 앱을 사용할 수 있습니다.
- Visual Studio: 추가 정보 대화 상자에서 앱을 만들 때 ASP.NET Core Hosted 확인란을 Blazor WebAssembly 선택합니다. 이 문서의 예제에서는 솔루션의 이름을 지정
BlazorHosted합니다. - Visual Studio Code/.NET CLI 명령 셸:
dotnet new blazorwasm -ho(옵션 사용-ho|--hosted). 이-o|--output {LOCATION}옵션을 사용하여 솔루션에 대한 폴더를 만들고 솔루션의 프로젝트 네임스페이스를 설정합니다. 이 문서의 예제에서 솔루션의 이름은BlazorHosted(dotnet new blazorwasm -ho -o BlazorHosted)입니다.
이 문서의 예제에서 클라이언트 프로젝트의 네임스페이스는
BlazorHosted.Client서버 프로젝트의 네임스페이스입니다BlazorHosted.Server.- Visual Studio: 추가 정보 대화 상자에서 앱을 만들 때 ASP.NET Core Hosted 확인란을 Blazor WebAssembly 선택합니다. 이 문서의 예제에서는 솔루션의 이름을 지정
프로젝트에서 파일을 삭제합니다
wwwroot/index.htmlBlazor WebAssembly.ClientClient 프로젝트에서 다음 줄을 삭제합니다.
Program.cs- builder.RootComponents.Add<App>("#app");Pages/_Host.cshtml프로젝트의 Server 폴더에Pages파일을 추가합니다. 명령 셸의 명령을 사용하여 템플릿_Host.cshtml에서 Blazor Server 만든 프로젝트에서 파일을 가져올dotnet new blazorserver -o BlazorServer수 있습니다(-o BlazorServer이 옵션은 프로젝트에 대한 폴더를 만듭니다). 호스트Pages/_Host.cshtml된 Server 솔루션의 Blazor WebAssembly 프로젝트에 파일을 배치한 후 파일을 다음과 같이 변경합니다.프로젝트에 대한
@using지시문을 Client 제공합니다(예:@using BlazorHosted.Client).WebAssembly 프로젝트의 스타일시트를 가리키도록 스타일시트 링크를 업데이트합니다. 다음 예제에서 클라이언트 프로젝트의 네임스페이스는 다음과 같습니다
BlazorHosted.Client.- <link href="css/site.css" rel="stylesheet" /> - <link href="_content/BlazorServer/_framework/scoped.styles.css" rel="stylesheet" /> + <link href="css/app.css" rel="stylesheet" /> + <link href="BlazorHosted.Client.styles.css" rel="stylesheet" />Note
<link>부트스트랩 스타일시트(css/bootstrap/bootstrap.min.css)를 요청하는 요소를 그대로 둡니다.다음을 사용하여
render-mode루트 구성 요소를 미리 렌더링하도록AppWebAssemblyPrerendered태그 도우미를 업데이트합니다.- <component type="typeof(App)" render-mode="ServerPrerendered" /> + <component type="typeof(App)" render-mode="WebAssemblyPrerendered" />클라이언트 쪽 Blazor 스크립트를 Blazor WebAssembly 사용하도록 스크립트 원본을 업데이트합니다.
- <script src="_framework/blazor.server.js"></script> + <script src="_framework/blazor.webassembly.js"></script>
Startup.ConfigureServer 프로젝트에서 파일에서index.html페이지로 대체를 변경합니다_Host.cshtml.Startup.cs:- endpoints.MapFallbackToFile("index.html"); + endpoints.MapFallbackToPage("/_Host");Client 및 Server 프로젝트가 미리 렌더링하는 동안 하나 이상의 일반적인 서비스를 사용하는 경우 서비스 등록을 두 프로젝트에서 호출할 수 있는 메서드로 팩터링합니다. 자세한 내용은 ASP.NET Core Blazor 종속성 주입을 참조하세요.
Server 프로젝트를 실행합니다. 호스트 Blazor WebAssembly 된 앱은 클라이언트용 프로젝트에서 미리 렌더링 Server 됩니다.
구성 요소를 페이지 또는 뷰에 포함하기 Razor 위한 구성
클라이언트 Razor 앱의 구성 요소를 서버 앱의 페이지 또는 뷰에 포함하기 Blazor WebAssembly 위한 이 문서의 다음 섹션과 예제에는 추가 구성이 필요합니다.
프로젝트에서 기본 Razor 페이지 또는 MVC 레이아웃 파일을 Server 사용합니다. 프로젝트에는 Server 다음 파일과 폴더가 있어야 합니다.
Razor 페이지:
Pages/Shared/_Layout.cshtmlPages/_ViewImports.cshtmlPages/_ViewStart.cshtml
MVC:
Views/Shared/_Layout.cshtmlViews/_ViewImports.cshtmlViews/_ViewStart.cshtml
Pages 또는 MVC 프로젝트 템플릿에서 만든 앱에서 Razor 이전 파일을 가져옵니다. 자세한 내용은 자습서: ASP.NET Core에서 페이지 시작 Razor 또는 ASP.NET Core MVC 시작을 참조하세요.
가져온 _ViewImports.cshtml 파일의 네임스페이스를 파일을 받는 프로젝트에서 사용 중인 네임스페이 Server 스와 일치하도록 업데이트합니다.
가져온 레이아웃 파일(_Layout.cshtml)을 프로젝트의 스타일을 포함 Client 하도록 업데이트합니다. 다음 예제 Client 에서 프로젝트의 네임스페이스는 .입니다 BlazorHosted.Client.
<title> 요소를 동시에 업데이트할 수 있습니다.
Pages/Shared/_Layout.cshtml(Razor 페이지) 또는 Views/Shared/_Layout.cshtml(MVC):
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>@ViewData["Title"] - DonorProject</title>
+ <title>@ViewData["Title"] - BlazorHosted</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
+ <link href="css/app.css" rel="stylesheet" />
+ <link href="BlazorHosted.Client.styles.css" rel="stylesheet" />
</head>
가져온 레이아웃에는 탐색 링크가 Home 포함됩니다Privacy. 호스팅 Home 된 앱에 Blazor WebAssembly 대한 링크를 가리키도록 하려면 하이퍼링크를 변경합니다.
- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
MVC 레이아웃 파일에서:
- <a class="nav-link text-dark" asp-area="" asp-controller="Home"
- asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
Privacy 링크를 개인 정보 페이지로 연결하려면 Server 프로젝트에 개인 정보 페이지를 추가합니다.
Pages/Privacy.cshtml 프로젝트에서 다음을 수행 Server 합니다.
@page
@model BlazorHosted.Server.Pages.PrivacyModel
@{
}
<h1>Privacy Policy</h1>
MVC 기반 개인 정보 보기를 선호하는 경우 Server 프로젝트에서 개인 정보 보기를 만듭니다.
View/Home/Privacy.cshtml:
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
컨트롤러에서 Home 보기를 반환합니다.
Controllers/HomeController.cs:
public IActionResult Privacy()
{
return View();
}
기부자 프로젝트의 Server 폴더에서 프로젝트로 wwwroot 정적 자산을 가져옵니다.
-
wwwroot/css폴더 및 콘텐츠 -
wwwroot/js폴더 및 콘텐츠 -
wwwroot/lib폴더 및 콘텐츠
ASP.NET Core 프로젝트 템플릿에서 기부자 프로젝트를 만들고 파일이 수정되지 않은 경우 기부자 프로젝트의 전체 wwwroot 폴더를 프로젝트로 Server 복사하고 아이콘 파일을 제거할 favicon 수 있습니다.
Warning
정적 자산을 폴더와 ClientServer 폴더 모두에 wwwroot 배치하지 않습니다. 두 폴더에 동일한 파일이 있는 경우 각 폴더의 정적 자산이 동일한 웹 루트 경로를 공유하므로 예외가 throw됩니다. 따라서 두 폴더가 아닌 두 폴더에 wwwroot 정적 자산을 호스트합니다.
구성 요소 태그 도우미를 사용하여 페이지 또는 보기에서 구성 요소 렌더링
추가 구성을 포함하여 솔루션을 구성한 후 구성 요소 태그 도우미는 페이지 또는 보기의 앱에서 Blazor WebAssembly 구성 요소를 렌더링하기 위한 두 가지 렌더링 모드를 지원합니다.
다음 Razor Pages 예제 Counter 에서는 구성 요소가 페이지에 렌더링됩니다. 구성 요소를 대화형으로 Blazor WebAssembly 만들기 위해 스크립트는 페이지의 렌더링 섹션에 포함됩니다.
Counter()와 함께 구성 요소에 {ASSEMBLY NAME}.Pages.Counter 대한 전체 네임스페이스를 사용하지 않도록 하려면 클라이언트 프로젝트의 @using 네임스페이스에 대한 지시문을 추가 Pages 합니다. 다음 예제 Client 에서 프로젝트의 네임스페이스는 .입니다 BlazorHosted.Client.
프로젝트에서 다음을 Server 수행 Pages/RazorPagesCounter1.cshtml합니다.
@page
@using BlazorHosted.Client.Pages
<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
Server 프로젝트를 실행합니다. 에서 Razor/razorpagescounter1페이지로 이동합니다. 미리 렌더링된 Counter 구성 요소가 페이지에 포함됩니다.
RenderMode는 구성 요소에 대해 다음을 구성합니다.
- 페이지에 미리 렌더링되었습니다.
- 페이지에 정적 HTML로 렌더링할지 여부 또는 사용자 에이전트에서 Blazor 앱을 부트스트랩하는 데 필요한 정보를 포함할지 여부
매개 변수 전달과 RenderMode 구성을 포함하여 구성 요소 태그 도우미에 대한 자세한 내용은 ASP.NET Core의 구성 요소 태그 도우미를 참조하세요.
구성 요소에서 사용하는 정적 리소스와 앱에서 레이아웃 페이지를 구성하는 방법에 따라 추가 작업이 필요할 수 있습니다. 일반적으로 스크립트는 페이지 또는 보기의 Scripts 렌더링 섹션에 추가되고 스타일시트는 레이아웃의 <head> 요소 콘텐츠에 추가됩니다.
CSS 선택기를 사용하여 페이지 또는 보기에서 구성 요소 렌더링
추가 구성을 포함하여 솔루션을 구성한 후 호스트 Client 된 솔루션Blazor WebAssembly의 프로젝트에 루트 구성 요소를 추가합니다Program.cs. 다음 예제 Counter 에서 구성 요소는 일치하는 id요소를 선택하는 CSS 선택기를 사용하여 루트 구성 요소로 counter-component 선언됩니다. 다음 예제 Client 에서 프로젝트의 네임스페이스는 .입니다 BlazorHosted.Client.
Program.cs
Client 프로젝트에서 프로젝트 구성 요소의 Razor 네임스페이스를 파일 맨 위에 추가합니다.
using BlazorHosted.Client.Pages;
구성 builder 요소가 설정된 Program.cs후 구성 요소를 루트 구성 요소로 추가 Counter 합니다.
builder.RootComponents.Add<Counter>("#counter-component");
다음 Razor Pages 예제 Counter 에서는 구성 요소가 페이지에 렌더링됩니다. 구성 요소를 대화형으로 Blazor WebAssembly 만들기 위해 스크립트는 페이지의 렌더링 섹션에 포함됩니다.
프로젝트에서 다음을 Server 수행 Pages/RazorPagesCounter2.cshtml합니다.
@page
<div id="counter-component">Loading...</div>
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
Server 프로젝트를 실행합니다. 에서 Razor/razorpagescounter2페이지로 이동합니다. 미리 렌더링된 Counter 구성 요소가 페이지에 포함됩니다.
구성 요소에서 사용하는 정적 리소스와 앱에서 레이아웃 페이지를 구성하는 방법에 따라 추가 작업이 필요할 수 있습니다. 일반적으로 스크립트는 페이지 또는 보기의 Scripts 렌더링 섹션에 추가되고 스타일시트는 레이아웃의 <head> 요소 콘텐츠에 추가됩니다.
Note
앞의 예제에서는 앱이 미리 렌더링되고 CSS 선택기와 JSException Pages 또는 MVC 앱에 Blazor WebAssembly 통합된 경우 Razor 를 throw 합니다. 프로젝트의 Client 구성 요소 중 Razor 하나로 이동하면 다음 예외가 발생합니다.
Microsoft.JSInterop.JSException: '#counter 구성 요소' 선택기가 일치하는 요소를 찾을 수 없습니다.
이는 라우팅 가능한 Blazor WebAssembly 구성 요소와 앱을 미리 렌더링하고 통합하는 Razor 것이 CSS 선택기 사용과 호환되지 않으므로 일반적인 동작입니다.
추가 Blazor WebAssembly 리소스
- 어셈블리 지연 로드를 사용한 미리 렌더링 지원
-
Razor 미리 렌더링과 관련된 구성 요소 수명 주기 주제
-
구성 요소 초기화(
OnInitialized{Async}) -
구성 요소 렌더링 후(
OnAfterRender{Async}) - 미리 렌더링한 후 상태 저장 다시 연결: 섹션의 콘텐츠가 중점 Blazor Server 적이고 상태 저장 SignalR다시 연결이지만 호스트 Blazor WebAssembly 된 앱(WebAssemblyPrerendered)에서 미리 렌더링하는 시나리오에는 개발자 코드가 두 번 실행되지 않도록 하는 유사한 조건과 접근 방식이 포함됩니다. 미리 렌더링하는 동안 초기화 코드를 실행하는 동안 상태를 유지하려면 이 문서의 미리 렌더링된 상태 유지 섹션을 참조하세요.
- JavaScript interop을 사용한 미리 렌더링
-
구성 요소 초기화(
- 사전 렌더링과 관련된 인증 및 권한 부여 주체
- ASP.NET Core Blazor WebAssembly 호스트 및 배포
ASP.NET Core