0

五分钟了解 Blazor

 2 years ago
source link: https://segmentfault.com/a/1190000040800253
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

2019年4月中旬微软推出了 Blazor,当时的我感觉 Blazor 简直是个划时代的东西,竟然能让 C# 运行到浏览器中。想着以后可能没有 C/S 架构什么事儿了,可以卸载掉所有的 App,电脑上有个浏览器就够了。近来终于有了能够系统了解 Blazor 的时间,下面把我了解到信息写下来分享给你,希望能对你有所帮助。

Blazor 可以使用强类型语言 C# 来替换 JavaScript 实现逻辑,可以前后端复用逻辑,也可以使用 nuget 1 中的包。它的其中一部分是基于 WebAssembly 实现的,所以不依赖任何的插件,让我们来快速了解一下 Blazor 是如何让 C# 运行在浏览器中的吧。

Blazor 涉及技术

Blazor 2 是 apt.net core 生态的组成部分,所涉及到的技术也大部分和 .net 相关。

视图层,使用 Razor 3 技术进行前端的编排渲染。Razor是一种标记语法,是 asp.net core 的默认视图语法,最显著的特点是强类型(C#、VB等)的代码可以和 HTML 写在一个文件中,当然也可以分开。在 razor 文件中,@符号后面的都是强类型语言,可以是一行中的一部分,也可以是一整行,还可以是一个段落。在 asp.net core 中的大致做法是把 VB、C# 等强类型语言嵌入到网页,当网页被请求的时候,在服务器端执行嵌入的代码,动态生成页面。

以 Blazor WebAssembly 开发方式运行时,依赖 WebAssembly 4 技术,可以做成静态页面不依赖任何后端服务器。

以 Blazor Server 方式开发运行时,依赖 SignalR 5 技术,并且需要后端服务器端配合。

Blazor 简介

Blazor 是一个使用 .NET 生成的交互式客户端 Web UI 的框架。和前端同学所熟知的 Vue、React、Angular 有巨大差异。

其最大的特色是使用 C# 代码(理论上可以是 .NET 生态的任何语言)代替 JavaScript 来实现逻辑。

有两种不同开发模式

Blazor WebAssembly, C# 代码运行在浏览器中。
Blazor Server,C# 代码在服务器端执行,使用 SignalR 同步到浏览器进行更新。

Blazor WebAssembly

让我们先简单了解一下 WebAssembly (Wasm)4

WebAssembly 是一种基于堆栈虚拟机的二进制指令格式。
WebAssembly 是一种类汇编语言。
WebAssembly 性能高、可以和JavaScript协作。
WebAssembly 是W3C的一部分,现代化的浏览器都已经支持。

那么现在让我们来思考一个问题,如何让 C# 代码,在浏览器中运行?

首先简单回忆一下 C# 代码是如何运行起来的。如下图所示,我们首先要把 C# 源码进行编译成 dll 文件,然后由 .net runtime 进行加载执行。

image.png

那如何让 C# 在浏览器中运行起来呢?看起来只缺少一个在浏览器中运行的 .net runtime。所以要用 JavaScript 来写一个 .net runtime 吗?不要着急,dotnet 社区有更好的方案。

在 dotnet/runtime 6 源码的 Directory.Build.props 7 文件中,我们可以看到,是有以 wasm 为编译目标的,也就是基于 WebAssembly 实现的 .net runtime 。现在我们已经知道 C# 代码可以运行在浏览器中了, Blazor 的生存土壤也就有了。(当然,事实情况是 mono 社区最先实现 WebAssembly 版本的 .net runtime。后来才合并到 dotnet core runtime 中)

接下来看一下如何创建 Blazor 工程。有两种方式,1、使用命令行,2、使用IDE,如 Visual Studio 。

命令行工具,仅供不想安装 Visual Studio 这类巨型工具,还想尝鲜的同学使用。可搭配任何编辑器,比如 Visual Studio Code。以下是具体步骤:

首先,需要下载 dotnet core 8。这里顺便给出 dotnet core 删除工具 dotnet-core-uninstall 9
使用命令 donet new -l 可以看到所有支持的模板。
在空白目录中使用命令 dotnet new blazorwasm 来创建 Blazor WebAssembly 的模板工程。
执行命令 dotnet run 启动网站,可以在浏览器中访问了。
使用 Visual Studio 创建就更为简单,选择对应的模板即可。

终于到了能上代码的时间了!

先来看两个关键文件,C# 的入口文件 Program.cs 和 HTML 的入口文件 index.html 。

// Program.cs 文件
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Net.Http;
using System.Threading.Tasks;
 
 
namespace BlazorWebAssembly
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("#app");
            // 上一行我们可以理解为,在 ID 是 app 的元素中渲染展示 Blazor WebAssembly,所以让网页的某一部分使用 Blazor 技术渲染也是可行的。
 
            builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
 
            await builder.Build().RunAsync();
        }
    }
}
<!-- index.html 文件 -->
<!DOCTYPE html>
<html>
 
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>BlazorWebAssembly</title>
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/app.css" rel="stylesheet" />
    <link href="BlazorWebAssembly.styles.css" rel="stylesheet" />
</head>
 
<body>
    <div id="app">Loading...</div>
 
    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">X</a>
    </div>
    <script src="_framework/blazor.webassembly.js"></script>
    <!-- blazor.webassembly.js 文件的作用有两个。
    1、下载 .net runtime, 依赖的类库以及项目编译后的文件。
    2、从 blazor.boot.json 中找到 C# 程序入口,并初始化运行。 -->
</body>
 
</html>

在编译之后的文件中,我们可以看到一些后缀名是 br 的文件,是因为 Blazor 默认使用了压缩率更高的 brotli 10 进行压缩,我觉得在这里应该推荐一下,brotli 比 gzip 更能节省空间。

image.png
Blazor WebAssembly 方式开发的简单架构,如上图所示,.net 代码的执行和 DOM 元素的渲染重绘都是在浏览器中进行的。

缺点:首次打开网站时需要加载大量依赖文件( .net runtime 以及依赖的各种类库);需要浏览器支持 WebAssembly 。在 caniuse 中可以查看到各浏览器对 WebAssembly 的支持情况 11

C# 和 JavaScript 的交互操作

有两种不同的交互方式,1、从 C# 调用 JavaScript 的代码 12,2、从 JavaScript 调用 C# 的代码 13

首先,从 C# 调用 JavaScript 的代码

先写一个 JavaScript 的全局函数,准备给 C# 使用。

function buildObjctString(name, age) {
    const obj = { name, age }
    return JSON.stringify(obj)
}

在 C# 中就可以这么调用

@inject IJSRuntime JS
 
private async Task CSharpCallJS()
{
    var methodName = "buildObjctString";
    var name = "zpfe group";
    var age = 18;
    var data = await JS.InvokeAsync<string>(methodName, name, age);
}

然后,从 JavaScript 调用 C# 的代码

// 这里的 C# 代码也是拿全局函数来示例,在函数头上加了注解。
[JSInvokable]
public static Task<string> GetTime(string param)
{
    return Task.FromResult($"{param},后面的来自C# {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
}

在 JavaScript 中的调用方式是

// 如果 C# 函数有参数,不传递会报错
const result = await DotNet.invokeMethodAsync("BlazorWebAssembly", "GetTime", "这个是 js 传入的参数");
alert(result)

这里只是最简单的例子,更详尽的还请从参考链接 1213中查看 。

使用 Visual Studio 调试将会很容易,和普通的 C# 调试方式一样,只在需要调试的代码最前面用鼠标点出调试的断点,按下 F5 就可以调试了。JavaScript 代码也可以使用相同的方式进行调试。

Blazor Server

个人认为 Blazor Server 是为了弥补 Blazor WebAssembly 的不足而创造出来的。Blazor Server 开发方式将会强依赖 SignalR 5 。这里先简单介绍一下 SignalR ,它也源自 ASPNET Core 社区,是基于 RPC 协议的一种实现。简单来说,就是可以在浏览器中使用 JavaScript 代码通过 SignalR 来调用服务器上开发的函数,也可以在服务器上使用 SignalR 来调用浏览器中的 JavaScript 函数。这种方式能够避免网站首次打开时需要加载大量依赖文件的问题,也能够弥补浏览器对WebAssembly的支持问题,甚至能够在 IE 中运行。但是这种方式开发的网站 UI 更新、事件处理等都需要通过 SignalR 调用服务器进行处理,需要和服务器频繁交互数据,对服务器算力要求颇高。以我的理解这种方式只适合用户量不大的网站。

使用命令创建的方式是 dotnet new blazorserver

使用 Visual Studio 创建就不讲了。

image.png
以 Blazor Server 开发方式的简单架构,如上图所示。 所有使用 C# 处理的 UI 更新,都需要在服务器端进行,通过 SignalR 技术将更新结果发送到浏览器中进行更新。用 C# 编写的事件处理函数以及 C# 和 JavaScript 之间的互操作 ,也需要相同的逻辑。

Other

我觉得比较有意思的两个功能 1、Blazor Destkop (.net core 6 将会支持),使用 Blazor WebAssembly 的方式开发桌面应用。2、Browser extension (开源社区的创意 14),使用 Blazor WebAssembly 的方式开发浏览器插件。

更多更有意思的项目请关注 awesome blazor 15

文中涉及到的代码已经共享到了 GitHub 16



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK