写在前面
曾经我和前端朋友聊天的时候,我说我希望有一天可以用C#写前端,不过当时更多的是美好的想象,而现在这一切正变得真实……
什么是Blazor
我们知道浏览器可以正确解释并执行JavaScript代码,那么浏览器是如何执行C#代码的呢?答案是通过WebAssembly。通过WebAssembly,我们可以让浏览器运行很多的高级语言,如 C#、C、C++、GO等,并使他们运行在基于内存安全的沙箱环境中。如下图所示:
作为一个已经五六年没有写过前端的.NET程序员,遇到Blazor实在是幸运中的幸运。它又让我可以很愉快的写前端了,而且还是用C#去写,我也就不用再分出精力去学习其他的JS框架了。
我们可以认为Blazor是.NET对WebAssembly的实现。通过使用Blazor,我们可以使用C#语言来取代JS去开发交互式Web UI。
值得一提的是,Blazor是由Browser和Razor这两个单词合并而成的,意思就是Blazor可以基于客户端执行Razor视图后将HTML呈现给浏览器。所以想要更好的理解Blazor,就要首先更好的了解浏览器和Razor。
Blazor有以下几个优点:
- 使用C#来取代JavaScript创建丰富的交互式UI
- 基于.NET及其生态编写服务器端和客户端应用程序逻辑
- 糅合现有HTML和CSS技术,提供了广泛的浏览器支持,包括移动浏览器(注意:Blazor取代的是基于JavaScript的UI交互,而其他部分如HTML、CSS,这些是我们的技术基础)
- 与现代托管平台(例如Docker)集成。
- Blazor是开源的,其源码位置在GitHub上
另外需要注意的,Blazor和Silverlight不可混为一谈,Blazor是基于开放标准而构建的,本身不需要任何额外插件。而Silverlight带有太多自有特性,所以不得不在浏览器上安装插件以更好的支持其运行。
什么是WebAssembly
概览
WebAssembly是一种二进制格式的指令集,其设计目标是能够在解释或者将其编译为本地机器代码并执行他们的机器上运行,这类似于我们.NET编译后的IL。
WebAssembly可以作为编译高级编程语言的可移植目标,通过节省大小和加载时间,充分利用各种平台(移动平台和IOT平台)上的通用应用功能,使得WebAssembly可以以接近于本机(接近于本机的英语单词是:near-native,在语言学里意思是精通语言的人,所说的话和说母语的人没有什么区别)的运行速度运行。
支持
WebAssembly已经获得了大部分浏览器的支持。详细内容可以移步至Can I Use
手写一个例子
接下来我们看一个例子,方便起见,我们直接使用在线的WebAssembly编译工具,地址是:https://mbebenita.github.io/WasmExplorer/。目前,这个工具只支持C和C++。不过也没有什么关系,我们写一个简单的方法用于测试即可。
- 首先我们定义了一个计算两个数和的方法:
1 int Addition(int a, int b) 2 { 3 return a + b; 4 }
- 然后点击COMPILE
在中间的框里会生成WAT(即WebAssembly文本格式)的代码,最右边的是二进制了。中间的代码部分可以帮助我们查看在编译的过程中发生了什么,会看到生成了一个名为_Z8Additionii的function,其中8表示这个方法名的长度,后面的i表示有多个参数,接下来我们会去调用它。
1 (module 2 (table 0 anyfunc) 3 (memory $0 1) 4 (export "memory" (memory $0)) 5 (export "_Z8Additionii" (func $_Z8Additionii)) 6 (func $_Z8Additionii (; 0 ;) (param $0 i32) (param $1 i32) (result i32) 7 (i32.add 8 (get_local $1) 9 (get_local $0) 10 ) 11 ) 12 )
- 点击Download,下载.WAT文件
- 接下来我们再写一个HTML网页出来,就用那种最简单的HTML代码,代码如下:
1 <HTML> 2 <HEAD> 3 <TITLE>WebAssembly Sample: Call C++ Code</TITLE> 4 <script type="text/javascript"> 5 let addition = fetch('test.wasm') 6 .then(response => response.arrayBuffer()) 7 .then(buffer => WebAssembly.compile(buffer)) 8 .then(module => { return new WebAssembly.Instance(module) }) 9 .then(instance => { addition = instance.exports._Z8Additionii }); 10 </script> 11 </HEAD> 12 <BODY BGCOLOR="FFFFFF"> 13 <h1>WebAssembly Sample: Call C++ Code</h1> 14 </BODY> 15 </HTML>
- 最终的效果图
通过以上示例,我们基本上对Blazor和WebAssembly的部分运行机制有了一个比较清晰的认识了,接下来,我们继续讨论有关Blazor的内容。
参考链接:
https://webassembly.github.io/spec/js-api/index.html