你好,Blazor

你好,Blazor

随着 .NET 5.0 预览版的出现,Blazor 也正式发布了,之前写过一个英雄联盟的战绩查询网站,用的是初代的 Blazor ,现在 dotnet 5.0 preview 也正式更新了全新的 Blazor,我也是第一时间体验,毕竟大家都是有经验的程序员,我们只从技术选型,开发体验,框架设计等维度,浅层的聊一聊,

Web 开发与 JavaScript 开发向来是同义词。直到 WebAssembly 的横空出世,WebAssembly (Wasm)是一种在浏览器中可以执行的二进制指令。 WebAssembly 的 官方工具链 能够编译 C/C++ 代码,但许多社区也提供了不同语言的编译器,如 Rust,Python,Java 和 Blazor(C#)。特别是 Rust 社区非常活跃,可以开始看到完整的前端框架,如 Yew 和 Dodrio,这为基于浏览器的应用带来了更多新的可能性,只要测试一些使用 WebAssembly 构建的优秀应用,就可知道基于浏览器的近乎原生的应用现在已经成为现实,例如 Sketchup 或 Magnum。
WebAssembly 被设计为可以和 JavaScript 一起协同工作——通过使用 WebAssembly 的 JavaScript API,你可以把 WebAssembly 模块加载到一个 JavaScript 应用中并且在两者之间共享功能。这允许你在同一个应用中利用 WebAssembly 的性能和威力以及 JavaScript 的表达力和灵活性。

接下来我们就来看一下如何快速构建一个 Blazor 应用。

1. 安装 Dotnet Core 3.0

Windows / Linux / Mac OS 同学可以在这里手动下载安装:

https://dotnet.microsoft.com/download

Windows Chocolatey 用户可以这样:

1
choco install dotnetcore

Linux Apt-Get 用户可以这样:

1
sudo apt-get install dotnet-sdk-3.1

Mac OS Homebrew 用户可以这样

1
brew cask install dotnet-sdk

安装结束以后可以看一下支持的快速构建模版,命令:

1
dotnet new -l

这里就是所有支持的模版,好了,开发环境就已经准备好了。

2. 创建 Blazor 项目

我们直接使用 dotnet 的模板命令:

1
dotnet new blazorserver -o HelloBlazor

通过几秒钟的等待,一个 Blazor Server App 就创建出来了,我们使用 VS Code 打开项目,来解读一下项目文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
├── App.razor                                         #负责 Assembly 组建的注入
├── Startup.cs #启动器,负责IOC注入,配置注入等
├── Program.cs #程序主入口
├── _Imports.razor #导入项声明
├── appsettings.Development.json #开发环境配置文件
├── appsettings.json #生产环境配置文件
├── HelloBlazor.csproj #项目文件
├── Data
│   ├── WeatherForecast.cs #天气业务模型
│   └── WeatherForecastService.cs #天气服务
├── Pages
│   ├── Counter.razor #计数器视图
│   ├── Error.razor #错误视图
│   ├── FetchData.razor #加载数据视图
│   ├── Index.razor #Home视图
│   └── _Host.cshtml #主视图,布局页
├── Properties
│   └── launchSettings.json #启动配置
├── Shared
│   ├── MainLayout.razor #页面主布局
│   ├── NavMenu.razor #导航菜单
│   └── SurveyPrompt.razor #提示页
└── wwwroot #站点资源,样式表,JS,字体,图标
├── css
│   ├── bootstrap
│   │   ├── bootstrap.min.css
│   │   └── bootstrap.min.css.map
│   ├── open-iconic
│   │   ├── FONT-LICENSE
│   │   ├── ICON-LICENSE
│   │   ├── README.md
│   │   └── font
│   │   ├── css
│   │   │   └── open-iconic-bootstrap.min.css
│   │   └── fonts
│   │   ├── open-iconic.eot
│   │   ├── open-iconic.otf
│   │   ├── open-iconic.svg
│   │   ├── open-iconic.ttf
│   │   └── open-iconic.woff
│   └── site.css
└── favicon.ico

3. 深入解读 Blazor

路由

我们看到 Pages 页面下都会有

  • @page “/“
  • @page “/counter”
  • @page “/error”
  • @page “/fetchdata”

其实这些就是页面的路由,如果我们输入一个不存在的页面地址会发生什么呢? 这就是 App.razor 里头 NotFound 节点的作用了。

页面会直接显示规定的内容

1
2
3
4
5
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>


运行模式

首先 Blazor 可以以两种模式运行(他们有着很本质的区别):

  • Server-Side
  • Client-Side

Server-Side 也被称为 Blazor 服务器,它是完全运行于服务器上面,也就是说客户端的浏览器只是一个空壳页面,它不包含任何的逻辑和除了首页(通常会被称为‘_Host’)以外的任何页面,该种模式完全托管于服务器,UI 的修改已经前端所发生的一切事件都需要传往服务器进行计算。传输的过程使用的是 SignalR 的方式。

使用这种方式意味着对于服务器的带宽以及性能要求会极其之高,但是对于一些需要使用到 SignalR 的应用以及一些访问量不大的地方使用 SignalR 也许会有不小的用途,因为事件模式的驱动方式,会让我们的应用有很高的灵活性和无限可能,并且在无操作的情况下,网页仍需要定期发送心跳包确认服务器状态,若服务器无响应,则整个网页停止服务。

我们尝试关掉后台服务进程。

我们会发现页面提示我们连接异常

重新打开后台服务后,刷新页面,页面恢复正常工作

这表示 Server-Side 模式是长链接模式,应用场景可以为 IM 通讯,大数据展示等。


Client-Side 是 SPA(Single Page Application)应用,基于一种叫 WebAssembly 的技术,WebAssembly(wasm)是一个开发的 web 标准,它是一种很底层的类似于字节码的东西,WebAssembly 可以通过 JavaScript 访问浏览器的完整功能。在我们.NET 运行在浏览器之前,Blazor 会提前向浏览器发送一个可以运行在 WebAssembly 上的迷你版本的 mono,我们知道.NET 中的语言是可以运行在 mono 之上的,因此我们就等于变相的实现了在浏览器中运行.NET。并且所有代码都是在 JavaScript 沙盒中运行,也防御了许多不安全操作。

对于客户端模式,Blazor 是将整个项目程序集和运行时(mono)一同发送到了浏览器,通过 WebAssembly 对 JavaScript 互操作处理 DOM 节点和相关 api 的调用。

两种方式对比

事实上两种方式都有其优缺点,ServerSide 在访问量并不是那么大的时候,或者说你的服务器足够好的时候,可以很轻松的完成需要的任务,并且在网络聊天这种需要保持长期的网络连接的时候,ServerSide 显然是首选,对于一些博客、或者一些普通的以页面展示为目的的网站,ClientSide 显然要比 ServerSide 好一些,但是 ClientSide 有一个致命的缺点,也就是你的代码质量必须高,代码需要精简。因为你的程序集的大小会影响你的加载速度,因此我们应当尽可能缩小程序集。


中间件

在微软提供的模板上面,大体上还是和我们的 ASP.NET Core 是接近的。在依赖注入中,因为我们利用了 Razor 来实现 C#和 html 的混合编码以及我们使用的是 ServerSide 的 Blazor,注入代码如下:

1
2
3
4
5
6
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
}

第一行添加了 Blazor 页面的支持

第二行制定运行模式为 Server-Side

第三行注入了单例的 Weather Service

我们再看到 UseEndpoints 做了一些什么事情,首先看到代码:

1
2
3
4
5
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});

第一行,匹配我们的 signalR 的连接

第二行,会自动到 Pages 下面去找我们的页面文件

这一篇文章下来,大家对 Blazor 有了大致的了解,接下来的文章我打算讲解一下如何进行 Blazor 的实战开发。

评论