寫在前面
曾經我和前端朋友聊天的時候,我說我希望有一天可以用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