日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

WebAssembly和Blazor:解决了一个存在十年的老问题

發(fā)布時間:2023/12/4 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WebAssembly和Blazor:解决了一个存在十年的老问题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文要點

  • WebAssembly 是一種新的客戶端技術(shù),可以在所有現(xiàn)代瀏覽器(包括移動瀏覽器)中實現(xiàn)近乎原生的性能,而且不需要插件。

  • 許多語言,包括 C、C#、Go 和 Rust,都可以編譯成面向基于棧的 WebAssembly 虛擬機的代碼。

  • .NET 代碼可以在任何地方運行,包括瀏覽器內(nèi)部。

  • Blazor 是一個客戶端庫,它在 WebAssembly 上使用.NET 來支持借助 Razor 模板使用 C# 編寫的單頁應用程序。

  • Blazor 支持代碼重用和將遺留代碼移植到現(xiàn)代 Web 應用程序的能力。

在 2019 年 4 月中旬,微軟悄悄地推出了一個年輕的框架,從“一切皆有可能”的實驗階段過渡到“我們致力于實現(xiàn)這一目標”的預覽版。這個框架名為Blazor,因為它在瀏覽器中運行,并利用了一個名為 Razor 的模板系統(tǒng)或“視圖引擎”,促成了這個.NET 開發(fā)人員幾乎放棄了的場景。它不僅允許開發(fā)人員使用 C# 構(gòu)建客戶端代碼(不需要 JavaScript),還允許開發(fā)人員在沒有插件的情況下在瀏覽器中運行現(xiàn)有的.NET 標準 DLL。

Blazor 有兩種托管模式。本文主要關(guān)注客戶端版本。你可以閱讀“Blazor 服務器端托管模型”了解更多關(guān)于服務器端版本的信息。

Silverlight 的希望

在任何地方運行.NET 的夢想始于 2006 年,當時有一個名為“Windows Presentation Foundation/Everywhere(WPF/E)”的應用程序框架以 Silverlight 的形式向公眾發(fā)布。第一個版本支持通過 WPF 引入的聲明性用戶界面,即可擴展應用程序標記語言(Extensible Application Markup Language,簡稱 XAML)。該平臺提供了對 UI 元素的細粒度控制,并提供了自己的文檔對象模型(DOM),可以通過 JavaScript 訪問。

當 Silverlight 2 在 2008 年發(fā)布時,它通過一個作為瀏覽器插件運行的公共語言運行時(CLR)實現(xiàn).NET 的完全支持,從而加快了采用速度。開發(fā)人員可以使用任何.NET 語言來構(gòu)建 Web 應用程序,利用成熟的數(shù)據(jù)綁定模式,如 Model-View-ViewMode(MVVM),并使用 REST 或 Windows Communication Foundation(WCF)客戶端與 Web API 通信。看起來,.NET 開發(fā)人員可以擺脫 JavaScript 的束縛,不用再擔心跨瀏覽器測試,而是專注于一個具有公共代碼庫的平臺來交付他們的應用程序。

Silverlight 開發(fā)者不知道的是,2007 年對于這個平臺來說是艱難的一年。兩個看似不相干的事件發(fā)生了,最終導致了它的滅亡。首先,Web 超文本應用技術(shù)工作組(WHATWG)和萬維網(wǎng)聯(lián)盟(W3C)之間開始著手合作編寫將于 2008 年發(fā)布的 HTML5 規(guī)范初稿。

第二,2007 年 6 月 29 日,蘋果發(fā)布了 iPhone

每隔一段時間,我們就會有一件革命性的產(chǎn)品橫空出世,并徹底改變一切。
——史蒂夫?喬布斯

比賽開始了。手機幾乎是在一夜之間從帶有聯(lián)系人列表的翻蓋手機發(fā)展到帶有游戲和內(nèi)置網(wǎng)絡瀏覽器的便攜式電腦。在很短的一段時間內(nèi),Silverlight 的未來似乎充滿了希望。微軟對 iPhone 的回應是 Windows Phone 7,支持以 Silverlight 作為開發(fā)平臺。Chrome 支持即將到來。如果微軟能夠找到一種將 Silverlight 應用到 iPhone 和 Android 手機上的方法,那么“一次編寫,到處運行”的圣杯將最終被發(fā)現(xiàn)。

只是,它沒有找到。

出于許多原因,包括運行“瀏覽器中的虛擬機”的安全性考慮,以及潛在的電池消耗,通向瀏覽器插件的大門砰地關(guān)上了,特別是在移動設備上。業(yè)界開始期待 HTML5 在打造移動體驗方面的前景。微軟改變了自己的關(guān)注點,到 2011 年 Silverlight 5 發(fā)布時,大多數(shù)開發(fā)人員已經(jīng)看到了不祥之兆:不會再有新版本了。

HTML5 和 JavaScript 繼續(xù)贏得 Web 開發(fā)人員的青睞。jQuery 等工具對 DOM 進行了標準化,使構(gòu)建多瀏覽器應用程序變得更加容易,同時,瀏覽器引擎開始采用通用的 DOM 標準,使“一次構(gòu)建,到處運行”變得更加容易。Angular、React 和 Vue.js 等前端框架的爆炸式增長使單頁應用程序(SPA)成為主流,并鞏固了 JavaScript 作為瀏覽器操作系統(tǒng)首選語言的地位。

JavaScript 即平臺

2013 年 3 月,asm.js正式推出。其文檔把它描述為JavaScript 的一個嚴格子集,可以用作編譯器的一種低級、高效的目標語言。該規(guī)范本質(zhì)上定義了一組 JavaScript 約定,這些約定使通過提前編譯優(yōu)化代碼成為可能,并提供了強類型(JavaScript 本身是一種動態(tài)語言)和基于堆的內(nèi)存模型。

Asm.js 的推出使將 C/C++ 代碼編譯成 JavaScript 成為可能,從而開啟了一個新的可能性領域。對約定的限制使得“支持 asm.js”的引擎可以有效地將 JavaScript 編譯成高性能的本地代碼。為了更好地理解這是如何實現(xiàn)的,請考慮下面的 C 代碼片段:

該代碼有效地掃描一個字符串,尋找標記其結(jié)束的測試字符或零字節(jié),并計算偏移量。C++ 已經(jīng)可以使用一個名為Clang的工具編譯成字節(jié)碼,該工具與LLVM 工具鏈兼容。LLVM 是一組支持快速跨平臺編譯代碼的技術(shù)。一個名為Emscripten的項目利用該工具鏈來生成 asm.js。

使用 Emscripten 編譯 C++ 代碼可以生成幾十行高度優(yōu)化的 JavaScript。以下代碼經(jīng)過簡化,用于說明生成的內(nèi)容:

function find(buf, test) {

buf = buf|0;

var cur = buf|0;

var result = -1|0;

while (1) {

var check = HEAP8[cur>>0]|0;

var foundZero = (check) === (0);

if (foundZero) {

break;

}

var foundTest = (check) === (test|0);

if (foundTest) {

result = (cur - buf)|0;

break;

}

}

return result|0;

}

生成的 JavaScript 與所有瀏覽器兼容并且運行良好。帶零操作的異或(|0)可以很容易地將任何數(shù)字轉(zhuǎn)換為帶符號整數(shù)。在較老的瀏覽器中,這可以確保數(shù)字沒有小數(shù)部分。在現(xiàn)代瀏覽器中,該約定可以提前通知編譯器使用 32 位整數(shù)(使數(shù)學運算更快),而不是默認的 64 位浮點值。0 右移(>>0)可以防止溢出,它還聲明了一個“索引”整數(shù)類型,該類型在 HEAP8 上迭代,而 HEAP8 是一個可以在 asm.js 中使用的類型化的字節(jié)緩沖區(qū)。

在 asm.js 中沒有定義 for 循環(huán)。所有內(nèi)容都被轉(zhuǎn)換為 while(1) 循環(huán)。這使得應用編譯器優(yōu)化變得更容易。這些優(yōu)化非常有效,以至于一個團隊能夠?qū)?Unreal 4 引擎移植到 Web 瀏覽器中,以近乎原生的性能直接運行 3D 第一人稱視角游戲。

WebAssembly:新希望

時間很快來到 2017 年,WebAssembly發(fā)布了,這是一種基于棧的虛擬機的二進制指令格式。WebAssembly 提供了一個可移植的編譯目標(簡稱 Wasm),與 asm.js 相比,它有幾個優(yōu)點:

  • 作為字節(jié)碼格式,不需要解析腳本和預編譯來進行優(yōu)化。代碼可以直接翻譯成本機指令。與 asm.js 相比,加載和開始執(zhí)行代碼的啟動時間要快幾個數(shù)量級。

  • 字節(jié)碼格式是一種更緊湊的代碼交付方式。

  • Wasm 實現(xiàn)了自己的指令集,因此不受 JavaScript 語言的限制。

任何編譯成 asm.js 的代碼都可以把 WebAssembly 作為目標。對于前面的示例,編譯器標志的一個簡單修改就會生成一個擴展名為.wasm 的文件。該文件只有 116 字節(jié)長。盡管該文件包含字節(jié)碼,但也存在代碼的標準化文本表示形式,名為WebAssembly 文本格式。這是 WebAssembly 中 find 模塊的文本表示:

(module

(type $t0 (func (param i32 i32) (result i32)))

(import "env" "memory" (memory $env.memory 256 256))

(func $a (type $t0) (param $p0 i32) (param $p1 i32) (result i32)

(local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32)

get_local $p0

set_local $l0

loop $L0

get_local $l0

i32.load8_s

tee_local $l2

i32.eqz

set_local $l1

get_local $l0

i32.const 1

i32.add

set_local $l3

get_local $l1

i32.const 1

i32.xor

get_local $p1

i32.const 24

i32.shl

i32.const 24

i32.shr_s

get_local $l2

i32.ne

i32.and

if $I1

get_local $l3

set_local $l0

br $L0

end

end

i32.const -1

get_local $l0

get_local $p0

i32.sub

get_local $l1

select)

代碼大小進行了優(yōu)化,因此函數(shù)被重命名為了 a。

WebAssembly 現(xiàn)在是 1.x 穩(wěn)定版,支持所有的現(xiàn)代瀏覽器,包括手機。若干語言都以 Wasm 作為有效的編譯目標。你可以使用 C、C++、Go、Rust、TypeScript 和許多其他語言來構(gòu)建 WebAssembly 程序。它已經(jīng)應用于計算機視覺、音頻混合、視頻編解碼器支持、數(shù)字信號處理、醫(yī)學成像、物理模擬、加密、壓縮等解決方案中。

但是 C# 呢?

在 WebAssembly 推出之后,將. NET 框架的工作版本(包括它的公共語言運行時)移植到 WebAssembly 上運行的工作就立即開始了。

這一努力取得了成功。

瀏覽器和 Razor 視圖引擎

2017 年底,微軟軟件工程師 Steve Sanderson 在他的個人博客上宣布了 Blazor 的消息。當時,它“只是一個實驗”,并不是正式產(chǎn)品。它始于這樣一個問題:“我們?nèi)绾巫?NET 在 WebAssembly 中運行?”第一個答案是比較老的簡化版.NET 運行時,他能夠在幾個小時內(nèi)將其編譯成 Wasm 二進制文件。.NET 本身在瀏覽器中并不是非常有用:你需要一個 UI 和某種與用戶交互的方式。Razor 文件將標記和 C# 結(jié)合起來創(chuàng)建 Web 模板,基于這項扎實的工作,Blazor 添加了大量的服務,從數(shù)據(jù)綁定和依賴注入到可重用組件、布局,以及調(diào)用 JavaScript 和從 JavaScript 調(diào)用。所有這些服務結(jié)合使得使用.NET 和 C# 構(gòu)建單頁面應用程序(SPA)成為可能。

圖 1 默認 Blazor 應用程序

為什么會有人在意呢?開發(fā)人員最初對 Blazor 的反應非常積極,這主要是因為:

  • 它允許開發(fā)人員使用他們已經(jīng)熟悉的語言(C#)和框架(.NET)來構(gòu)建以前深深扎根在 JavaScript 中的客戶端應用程序。

  • 它可以在所有現(xiàn)代瀏覽器中運行,包括移動瀏覽器,而且不需要插件。

  • 它使開發(fā)人員能夠進入.NET 生態(tài)系統(tǒng)并“按原樣”使用現(xiàn)有的庫。例如,如果你正在構(gòu)建一個使用 Markdown 的博客引擎,那么你可以為現(xiàn)有的 Markdown 引擎安裝 NuGet 包,并將 Markdown 直接轉(zhuǎn)換為 HTML,以便在瀏覽器中預覽。

  • .NET 的性能會隨著時間的推移不斷提高,因此在瀏覽器的 Wasm 上運行已經(jīng)足夠了。

  • Blazor 是一個真正的單頁應用程序,它從一組靜態(tài)資產(chǎn)運行,可以使用Azure Storage 靜態(tài)網(wǎng)站等服務以非常低的成本托管這些靜態(tài)資產(chǎn)。

現(xiàn)在,你已經(jīng)了解了 Blazor 背后的歷史和動機,讓我們來研究一些技術(shù)細節(jié)。

本文中的所有代碼示例都可以在Blazor WebAssembly?GitHub 存儲庫中找到。

安裝 Blazor 并開始使用所需要了解的所有內(nèi)容都可以在Blazor 入門這篇文章中找到。在安裝了 Blazor 之后,你可以選擇只創(chuàng)建客戶端或帶有ASP.NET Core后端的客戶端。對于現(xiàn)有的基于 MVC 的服務器端項目來說,該項目看起來非常熟悉。但是,生成的 DLL 直接加載到瀏覽器中,并由.NET 的 WebAssembly 版本運行。

圖 2 Blazor 應用中的網(wǎng)絡活動

Mono.js?JavaScript 動態(tài)加載 mono.wasm 并開始在瀏覽器中運行.NET。其余的加載是組成應用程序的實際 DLL 文件。

瀏覽器中的 C#(帶依賴注入)

默認模板包含一個獲取模擬天氣信息的頁面。這是 Razor 視圖,完全由 Wasm 在客戶端上渲染。

<h1>Weather forecast</h1>


<p>This component demonstrates fetching data from the server.</p>


@if (forecasts == null)

{

<p><em>Loading...</em></p>

}

else

{

<tableclass="table">

<thead>

<tr>

<th>Date</th>

<th>Temp. (C)</th>

<th>Temp. (F)</th>

<th>Summary</th>

</tr>

</thead>

<tbody>

@foreach (var forecast in forecasts)

{

<tr>

<td>@forecast.Date.ToShortDateString()</td>

<td>@forecast.TemperatureC</td>

<td>@forecast.TemperatureF</td>

<td>@forecast.Summary</td>

</tr>

}

</tbody>

</table>

}

在模板的上部,一組指令決定了頁面的路徑,聲明了一個 using 指令,并使用依賴注入來獲取.NETFramework 的 HttpClient 副本,該副本可以在瀏覽器中使用。

@page "/fetchdata"

@using GetStarted.Shared

@inject HttpClient Http

最后,頁面上的一小段代碼嵌入到 @functions 塊中。這里需要注意的是,代碼完全是 C# 的。你可以使用熟悉的 HttpClient 執(zhí)行網(wǎng)絡操作,并且支持 async/wait。

WeatherForecast[] forecasts;


protected override async Task OnInitAsync()

{

forecasts = await Http.GetJsonAsync<WeatherForecast[]>("api/SampleData/WeatherForecasts");

}

視圖模板渲染一個頁面,但是控件呢?

可重用組件

Blazor 基于分層組件的可組合 UI。天氣預報組件與其他組件的唯一區(qū)別是提供路由的頁面指令。下面是一個名為 LabelSlider.razor 的組件的模板,使用一個顯示當前值的 span 擴展內(nèi)置的 HTML Input Range。

<inputtype="range"min="@Min"max="@Max"bind-value-oninput="@CurrentValue"/>

<span>@CurrentValue</span>


綁定語法的格式為 bind-{property}-{event}。事件是可選的,觸發(fā)事件時綁定會更新。如果沒有這個,滑塊只會在用戶停止移動滾動條時更新 span。通過連接到 oninput,該值將隨著滑塊的移動而刷新。

關(guān)聯(lián)的代碼暴露了參數(shù),這些參數(shù)允許父組件設置最小和最大范圍值,并將數(shù)據(jù)綁定到當前值。Action 屬性暴露一個與 CurrentValue 關(guān)聯(lián)的事件,并按照約定將其命名為 CurrentValueChanged,以方便雙向數(shù)據(jù)綁定(父組件可以“偵聽”更改事件并相應更新綁定值)。

[Parameter]

int ; set; }


[Parameter]

int ; set; }


private int _currentValue;


[Parameter]

int

{

get ;

set

{

if

{

_currentValue ;

CurrentValueChanged?.Invoke(value);

}

}

}


[Parameter]

Action<int> CurrentValueChanged ; set; }

注意,沒有使用 Parameter 屬性標記的屬性只對組件可見。組件重用非常簡單,只需把組件名置入標簽并提供必要的參數(shù),用法如下:

<LabelSlider Min="0" Max="99" bind-CurrentValue="@currentCount"/>

在本例中,一個與父組件上的 currentCount 屬性之間的雙向綁定建立起來了。

使用現(xiàn)有的庫

Blazor 的一個非常強大的優(yōu)點是能夠“按原樣”集成現(xiàn)有的類庫。例如,考慮一個使用Markdown的博客引擎,它能夠在瀏覽器中預覽生成的 HTML。在 Blazor 中構(gòu)建它就像安裝一個 NuGet 包一樣簡單,在本例中是開源的MarkDig處理器。然后,可以直接調(diào)用庫:

var html = Markdig.Markdown.ToHtml(SourceText);

NuGet DLL 像其他項目引用一樣被導入瀏覽器,并且可以從客戶端應用程序調(diào)用。

圖 3 瀏覽器中的 Markdown 轉(zhuǎn)換

調(diào)用 JavaScript/ 從 JavaScript 調(diào)用

Blazor 提供的一個重要服務是能夠從.NET 調(diào)用 JavaScript,反之亦然。你希望從 Blazor 調(diào)用的任何 JavaScript 方法都必須能夠從全局 window 對象訪問,調(diào)用方法如下:

window.jsAlert = msg => alert(msg);

該互操作功能的使用方式如下:

await JsRuntime.InvokeAsync<object>("jsAlert", "Wow!");

InvokeAsync 方法支持傳遞和返回值,這些值將自動在 JavaScript 與.NET 之間轉(zhuǎn)換并由 Blazor 運行時編組。使用 JsInvokable 屬性來暴露 C# 方法,以便可以從 JavaScript 調(diào)用它。下面是一個例子,它封裝了 Markdown 轉(zhuǎn)換調(diào)用:

public static class Markdown

{

[JSInvokable]

public static string Convert(string src)

{

return Markdig.Markdown.ToHtml(src);

}

}

從 JavaScript 調(diào)用 DotNet.invoke 方法并傳遞程序集名稱、暴露的方法名稱和任何參數(shù)。

圖 4 從 JavaScript 調(diào)用.NET

這使得擴展遺留應用程序和使用現(xiàn)有的 JavaScript 庫成為可能。你甚至可以從 Blazor 應用程序調(diào)用其他 WebAssembly 模塊。

Blazor 在發(fā)展

微軟將 Blazor 移出了實驗階段,進入了官方預覽版。使用組件模型進行服務器端渲染的 Blazor 版本將與.NET?Core 3 的最終版本一起發(fā)布(請參閱.NET Core 路線圖),客戶端版本將在隨后不久發(fā)布。還有工作要完成:調(diào)試體驗極其有限,必須改進;有機會通過提前編譯生成本機 Wasm 來優(yōu)化代碼性能;在將未使用的代碼庫發(fā)送到瀏覽器之前,需要從庫中刪除未使用的代碼,從而降低總體大小(這個過程稱為樹抖動)。對 WebAsssembly 的興趣和采用與日俱增,借助 Blazor,編寫可以在任何地方運行的 C# 和.NET 代碼的夢想終于實現(xiàn)了。

關(guān)于作者

Jeremy Likness是微軟 Azure 的云推廣專員。Jeremy 在 1982 年編寫了他的第一個程序,并且已經(jīng)開發(fā)企業(yè)應用程序 25 年了。他是四本科技書籍的作者,曾做過 8 年微軟 MVP,是國際性的主題演講家。Jeremy 的飲食以植物為主,在大部分空閑時間里,他都在太平洋西北部他的家附近跑步、徒步旅行和露營。關(guān)注Jeremy 的博客

原文地址:https://www.infoq.cn/article/GERYOPIV4B8OSD3_kSmB

.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?

總結(jié)

以上是生活随笔為你收集整理的WebAssembly和Blazor:解决了一个存在十年的老问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。