写点什么

五分钟了解 Blazor

发布于: 刚刚

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


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

Blazor 涉及技术

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


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


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


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

Blazor 简介

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


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


有两种不同开发模式


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

Blazor WebAssembly

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


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


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


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



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


在 dotnet/runtime 15 源码的 Directory.Build.props 16 文件中,我们可以看到,是有以 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 12。这里顺便给出 dotnet core 删除工具 dotnet-core-uninstall 13 。使用命令 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 8 进行压缩,我觉得在这里应该推荐一下,brotli 比 gzip 更能节省空间。



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


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

C# 和 JavaScript 的交互操作

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


首先,从 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)
复制代码


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

调试

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

Blazor Server

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


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


使用 Visual Studio 创建就不讲了。



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

Other

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


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


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


[0]: https://www.nuget.org/

[1]: https://docs.microsoft.com/zh-cn/aspnet/core/blazor/

[3]: https://docs.microsoft.com/zh-cn/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet

[4]: https://docs.microsoft.com/zh-cn/aspnet/core/blazor/javascript-interoperability/call-dotnet-from-javascript

[5]: https://docs.microsoft.com/zh-cn/aspnet/core/razor-pages

[6]: https://docs.microsoft.com/zh-cn/aspnet/core/signalr

[7]: https://webassembly.org/

[8]: https://github.com/google/brotli

[10]: https://github.com/mingyaulee/Blazor.BrowserExtension

[11]: https://github.com/AdrienTorris/awesome-blazor

[12]: https://dot.net

[13]: https://github.com/dotnet/cli-lab

[14]: https://caniuse.com/?search=WebAssembly

[15]: https://github.com/dotnet/runtime

[16]: https://github.com/dotnet/runtime/blob/main/Directory.Build.props#L33

[17]: https://github.com/cnryb/blazor-demo

发布于: 刚刚阅读数: 2
用户头像

zhaopin.com 2020.08.04 加入

作为智联招聘的前端架构团队,我们开创了细粒度的前端研发和发布模式,统一了移动端和桌面端的技术栈,搭建了灵活可靠的Serverless运行环境,率先落地了微前端方案,并且还在向FaaS和轻研发等方向不断迈进。

评论

发布
暂无评论
五分钟了解 Blazor