第一章 渲染模式与项目结构

Blazor

Blazor是一种前端 Web UI 框架,Blazor 应用由使用 C#、HTML 和 CSS 构建的可重复使用的 Web UI 组件构成,通俗的说就是可以使用C#来完成JavaScript的交互工作,从而替代JavaScript(当然,就目前而言是做不到完全不使用JavaScript的),减轻开发人员的学习负担或项目开发成本。

Blazor应用是基于组件进行开发的,这里的组件是指 UI 元素,例如页面、对话框或数据输入窗体。组件是内置到 .NET 程序集的 .NET C# 类,通常以 Razor 标记页(文件扩展名为 .razor)的形式编写。 Blazor 中的组件正式称为 Razor 组件,非正式地称为 Blazor 组件。

可以使用 Blazor 生成

  • 通过WebSocket(Blazor server)连接处理 UI 交互的服务器端代码。
  • 通过WebAssembly直接在浏览器中运行的客户端 Web 应用。

WebAssembly

WebAssembly是W3C标准中的内容,是一种虚拟的指令集架构,可以在Web浏览器中运行汇编语言(底层+高性能)。W3C标准长久以来都是由HTML+CSS+javascript构成,到了2019年之后,才加入了WebAssembly,也就是说在2019年之后出现的浏览器,都支持WebAssembly,可见其重要性。

我们的程序之所以可以在电脑上运行,是因为CPU上的指令集架构,例如Intel AMD X86-64 架构以及ARM架构,我们的代码最终转换成这些架构可以执行的指令集,然后得以在CPU上运行,这些架构也称为物理架构(ISA= Instruction Set Architecture)。WebAssembly也是一套指令集架构,只不过它依托于软件上运行,因此也称为虚拟架构V-ISA。与物理架构相同,只要将代码转为对应的指令集,只要Web浏览器上可以支持WebAssembly,那么理论上所有的编程语言都可以在Web浏览器上运行。

Blazor的渲染模式

Blazor Web 应用中的每个组件会采用不同的渲染模式来确定其使用的托管模型、渲染位置以及它是否是交互式的。

一、预渲染

预渲染是指首次在服务器上渲染页面内容时的过程,这个过程中为了根据请求尽快地输出HTML页面,并没有给渲染控件启用事件处理程序。

预渲染可以让用户感觉到更快的响应,而且可以通过渲染搜索引擎,改进SEO。

默认情况下,交互式组件会启用预呈现,要禁用组件实例的预渲染,可以向渲染模式传递值为 falseprerender 标志。

对组件实例禁用

<... @rendermode="new InteractiveAutoRenderMode(prerender: false)"/>

在组件定义中禁用

@rendermode @(new InteractiveAutoRenderMode(prerender: false))

全局组件禁用

  • App.razor

    <!DOCTYPE html>
    <html lang="en">
    <head>
        ......
        <HeadOutlet @rendermode="new InteractiveAutoRenderMode(prerender: false)" />
    </head>
    
    <body>
        <Routes @rendermode="new InteractiveAutoRenderMode(prerender: false)" />
        <script src="_framework/blazor.web.js"></script>
    </body>
    
    </html>
    

二、静态服务端渲染(静态SSR)

默认情况下(没用指定渲染模式),组件会使用静态服务端渲染。如下例所示,在没有指定组件渲染模式时,组件在服务器上是静态渲染的。点击按钮后并不会调用UpdateMessage方法,message的内容也不会改变。

  • 示例

    @page "/render-mode-1"
    
    <button @onclick="UpdateMessage">Click me</button> @message
    
    @code {
        private string message = "Not clicked yet.";
    
        private void UpdateMessage()
        {
            message = "Somebody clicked me!";
        }
    }
    

在 Blazor Web App(Auto)应用中,静态服务端渲染的组件,应该放置在不以 .Client 结尾的项目的Components\Pages下。

三、交互式服务器端渲染-SSR(Blazor Server)

Blazor在 ASP.NET Core 应用中添加了对在服务器上托管 Razor 组件的支持。 可通过 SignalR 连接处理 UI 更新。服务端与用户的交互通过服务器与浏览器的实时连接进行处理。

在 Blazor Web 应用中,交互式服务器端渲染的组件,应该放置在不以 .Client 结尾的项目的Components\Pages下。

运行时停留在服务器上并处理

  • 执行应用的 C# 代码。
  • 将 UI 事件从浏览器发送到服务器。
  • 将 UI 更新应用于服务器发送回去的渲染组件。
    在这里插入图片描述

优点

  • 下载项大小明显小于使用 Blazor WebAssembly 托管模型时的大小,并且应用加载速度要快得多。
  • 应用可以充分利用服务器功能,包括对 .NET Core API 的使用。
  • 服务器上的 .NET Core 用于运行应用,因此调试等现有 .NET 工具可按预期正常工作。
  • 支持瘦客户端。 例如,Blazor Server 适用于不支持 WebAssembly 的浏览器以及资源受限的设备。
  • 应用的 .NET/C# 代码库(其中包括应用的组件代码)不适用于客户端。

缺点

  • 实时性限制:Blazor Server 使用了 SignalR 技术来实现与服务器的实时通信,但由于所有的 UI 更新都需要通过服务器来完成,因此在网络延迟较高的情况下,用户可能会感受到明显的延迟。这对于在线工具或游戏等需要实时响应的应用来说是不可接受的。
  • 服务器资源消耗:Blazor Server 的工作原理是将整个应用部署在服务器上,每个用户都会占用一个连接和一些服务器资源。对于在线工具或游戏等需要大量用户同时在线的应用来说,这可能会导致服务器资源消耗过大,难以扩展和维护。
  • 客户端性能限制:Blazor Server 的 UI 渲染是在服务器上完成的,然后通过 SignalR 将更新的 UI 推送到客户端。这意味着客户端的性能对于应用的响应速度和用户体验有很大影响。对于一些复杂的在线工具或游戏来说,客户端的性能可能无法满足需求。
  • 不支持脱机工作。 如果客户端连接失败,交互性将失效。
  • 需要 ASP.NET Core 服务器为应用提供服务。 无服务器部署方案不可行,例如通过内容分发网络 (CDN) 为应用提供服务的方案。

综上所述,Blazor Server 更适合开发那些对实时性要求不高、用户量较小、对服务器资源消耗要求不高的网站应用。对于在线工具或游戏等需要实时性和大量用户同时在线的应用,Blazor WebAssembly 可能更适合,因为它可以将整个应用部署到客户端,减轻了服务器的负担,并提供了更好的用户体验。

四、客户端渲染-CSR(Blazor WebAssembly)

使用 Blazor WebAssembly,开发人员可以在浏览器中运行 .NET 代码。 它是一种单页应用框架,使用的是 WebAssembly 开放标准,无需插件或代码生成。

浏览器中通过 WebAssembly 执行的 .NET 代码在浏览器的 JavaScript 沙盒中运行。 该代码具有沙盒提供的所有安全和保护特性。 这有助于防止客户端计算机上的恶意操作。

Blazor 使用编译为 WebAssembly 模块的 .NET 运行时,该模块随应用一起下载。 该模块可执行 Blazor 应用中包含的 .NET 标准代码。

Blazor WebAssembly 应用仅限于执行该应用的浏览器的功能,但该应用可以通过 JavaScript 互操作访问完整的浏览器功能。

在 Blazor Web 应用中,客户端渲染的组件,应该放置在以 .Client 结尾的项目的Components\Pages下。

在这里插入图片描述

如果创建了 Blazor WebAssembly 应用进行部署,但没有后端 ASP.NET Core 应用来为其文件提供服务,那么该应用被称为独立Blazor WebAssembly 应用。当独立 Blazor WebAssembly 应用使用后端 ASP.NET Core 应用提供其文件时,该应用称为托管 Blazor WebAssembly 应用。

托管客户端应用可以使用各种消息传递框架和协议(例如 Web API、gRPC-Web 和 SignalR(结合使用 ASP.NET Core SignalR 和 Blazor))通过网络与其后端服务器应用进行交互。

优点

  • 即时性能:Blazor WebAssembly利用WebAssembly(Wasm)技术,将C#代码编译成高效的二进制格式,可以在浏览器中直接运行。这意味着您可以在客户端使用C#编写的应用程序,而无需将其转换为JavaScript。这种直接运行的能力使得Blazor WebAssembly具有接近原生应用程序的性能,为用户提供更快的加载速度和更流畅的用户体验。
  • 跨平台:Blazor WebAssembly是一个跨平台的解决方案,可以在各种操作系统和设备上运行,包括Windows、Mac、Linux和移动设备。这意味着您可以使用相同的代码库构建适用于不同平台的应用程序,从而减少开发和维护的工作量。
  • 开发效率:Blazor WebAssembly使用C#语言和.NET框架,这是一个广泛使用的开发工具和生态系统。如果您已经熟悉C#和.NET,那么您可以立即开始使用Blazor WebAssembly进行开发,无需学习新的语言或框架。这种开发效率可以大大加快项目的开发速度,并减少开发人员的学习曲线。
  • 对于独立 Blazor WebAssembly 应用,从服务器下载应用后,没有 .NET 服务器端依赖项,因此,如果服务器脱机,应用将保持正常运行。
  • 安全性:Blazor WebAssembly应用程序在客户端运行,但它们是在沙箱环境中执行的,与原生应用程序相比,它们具有更高的安全性。这意味着您可以在客户端执行敏感操作,而无需担心安全问题。此外,由于使用C#编写代码,您可以利用.NET的安全功能来保护应用程序免受常见的安全漏洞和攻击。

缺点

  • Razor 组件仅可使用浏览器功能。
  • 需要可用的客户端硬件和软件(例如 WebAssembly 支持)。
  • 下载项大小较大,初次组件加载耗时较长。
  • 发送到客户端的代码无法防止用户进行检查和篡改。

五、Auto(自动渲染

自动渲染会决定如何在运行时渲染组件。 该组件一开是会使用 Blazor Server 托管模型,通过交互式服务器端的方式进行渲染。 .NET 运行时和应用捆绑包会在后台下载到客户端并缓存,以便将来访问时可以使用它们。

简单地说就是结合使用Blazor Server和Blazor WebAssembly了,先渲染Blazor Server组件稳住用户,然后偷偷下载Blazor WebAssembly客户端,下载完了再进行WebAssembly组件的渲染。

在Blazor Web App项目下,使用Auto模式或Blazor WebAssembly模式进行渲染的组件必须放置在以 .Client 结尾的项目的Components\Pages下。

六、预渲染的坑

客户端服务在预渲染期间无法解析,官方文档中强调了这一点,大概的意思是预渲染时,无法使用客户端渲染模式中所注册的服务。下面的例子中,在Home组件上尝试注入 IWebAssemblyHostEnvironment 以获取环境的名称,会在项目运行时抛出异常。

  • 示例

    @page "/"
    
    @using Microsoft.AspNetCore.Components.WebAssembly.Hosting
    @inject IWebAssemblyHostEnvironment Environment
    
    <PageTitle>Home</PageTitle>
    
    <h1>Hello, world!</h1>
    
    Welcome to your new app.
    

其原因是,预渲染是在服务端进行的,但是IWebAssemblyHostEnvironment服务并不是在服务器端进行注册的。

在我们创建Blazor Web App项目时,选择Blazor Assembly模式或Auto模式,都会在解决方案中创建两个项目(一个以.Client结尾,一个不是),两个项目各自有自己的IOC容器,预渲染期间,使用的是不以.Client结尾的项目中的IOC容器,而客户端的服务是注册在以.Clent结尾的项目的IOC容器中的,所以在预渲染期间使用客户端的服务就是跨IOC容器了,这时候就出现异常。

要解决这个问题,有几种方式:

  • 对引用了客户端服务的组件,禁用预渲染模式,但是这并不符合组件规范(尽量适应任何渲染模式)。
  • 如果不对组件禁用预渲染,官方给出较为推荐的方式是,组件中所使用的服务,在服务端的IOC容器中再注册一次,具体的做法就是在不以.Client结尾的项目的Program类中,进行对应服务的注册。(个人感觉这一点很蛋疼,感觉像是在用一种半成品的感觉)

HttpClient服务举例,如果希望在客户端渲染的组件中使用HttpClient服务,且不禁用预渲染,那么需要在主项目和.Client项目中都注册HttpClient服务才行。

  • .Client项目的Program类中

    var builder = WebAssemblyHostBuilder.CreateDefault(args);
    
    //注册HttpClient服务
    builder.Services.AddScoped(sp =>
        new HttpClient
        {
            BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
        });
    
    await builder.Build().RunAsync();
    
  • 主项目的Program类中

    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.AddRazorComponents()
        .AddInteractiveServerComponents()
        .AddInteractiveWebAssemblyComponents();
    //注册HttpClient服务
    builder.Services.AddHttpClient();
    
    ......
    

项目结构

一、创建Blazor Web App

.Net8 推出了Blazor Web App,官方自述集合了Blazor Server和Blazor WebAssembly的优点,这里说一下创建项目的步骤。

打开 VS2022,点击创建新项目,选择Blazor Web App
在这里插入图片描述

在创建过程中有几个选项比较关键:

框架选择.net8,目前最新的为.net8,暂时也只有.net8有 Blazor web App模板。

取消勾选Https,调试环境下没必要打开这个,后面上线前可以在项目文件中修改。

Interactive render mode,交互渲染模式:在这里可以选择None(静态)、Blazor server、Blazor webAssemby或Auto(两者结合)。其中Auto是.Net8的新模式,当 .NET 应用捆绑包和运行时下载到浏览器时,自动渲染模式最初会使用交互式 SSR,激活 .NET WebAssembly 运行时后,渲染将切换到 CSR。

Interactive render mode,交互位置:Per page/component为设置每个页面或每个组件的交互性;Global则为整个应用设置全局交互性。仅当“交互式渲染模式”不是 None 且未启用身份验证时,才能设置交互位置。

  • Per page/component时,在每个组件中,单独通过@rendermode指定渲染模式。
    在这里插入图片描述
  • Global时,会在App组件中的Routes组件和HeadOutlet组件上通过@rendermode来指定全局的渲染模式,组件会将其渲染模式传播到它路由的页面。

在这里插入图片描述

  • 注意,Auto渲染模式下,这两个选项会导致项目结构的不同。

Include sample pages:包含基于 Bootstrap 样式的示例页面和布局。
在这里插入图片描述

二、项目结构

因为Auto模式的项目结构包含了其他几种模式,所以这里以Auto模式进行说明。

在项目完成创建之后,可以看到目录结构如下:
在这里插入图片描述

Auto或WebAssembly模式下,项目将额外包含一个客户端项目 (.Client), 所有需要使用WebAssembly模式或者自动交互模式进行渲染的组件都必须放在这个项目中,将其包含在下载应用捆绑包中。

Components 文件夹:其中存放了Layout 文件夹和Pages 文件夹以及一下项目相关的重要组件。

  • Layout 文件夹终于要存放布局组件和对应的样式表,其中MainLayout 组件为整个应用的布局组件;NavMenu 组件为边栏导航,其中使用了 NavLink 组件,该组件可向其他 Razor 组件渲染导航链接。、
  • Pages 文件夹主要存放应用的可路由的Razor组件,每个组件都使用@page指令来指定路径,
  • App 组件是整个应用的根组件,是应用加载的第一个组件,决定了整个应用的整体骨架。具有 HTML <head> 标记、Routes 组件和 Blazor<script> 标记,引入了基本的CSS、JS和。
  • Routes组件使用了Route组件设置路由。 对于客户端交互式组件,Router组件会截获浏览器导航并渲染与请求的地址匹配的页面。
  • _Imports.razor组件用于引用整个应用的组件的通用命名空间,如果该引用只在单独的组件中使用,可以在对应的组件中直接使用@using引用。

Properties 文件夹:存放 launchSettings.json 文件,其中保存了开发环境配置。

wwwroot 文件夹:服务器项目的 Web 根文件夹,包含应用的公共静态资产。

Program.cs 文件:服务器项目的入口点,用于设置 ASP.NET Core Web 应用程序主机,并包含应用的启动逻辑,包括服务注册、配置、记录和请求处理管道。

  • 通过调用AddRazorComponents添加 Razor 组件的服务。
  • 调用AddInteractiveServerComponents添加服务以支持渲染交互式服务器组件,AddInteractiveWebAssemblyComponents添加服务以支持渲染交互式 WebAssembly 组件。
  • 调用MapRazorComponents发现可用的组件并指定应用的根组件(一般为App.razor).
  • 调用AddInteractiveServerRenderMode为应用配置交互式服务器端渲染(交互式 SSR),AddInteractiveWebAssemblyRenderMode为应用配置交互式 WebAssembly 渲染模式。
  • appsettings.jsonappsettings.Development.json文件为应用的配置文件,前者用于生产环境,后者用于开发环境.
  • 13
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SchuylerEX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值