寫在前面
曾經我和前端朋友聊天的時候,我說我希望有一天可以用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.org/
https://webassembly.github.io/spec/js-api/index.html
https://caniuse.com/#search=wasm
https://webassembly.github.io/spec/js-api/index.html