來源 | OSCHINA 社區(qū)
作者 | 京東云開發(fā)者-京東物流 潘維高
1 WebAssembly 是什么?
一種運行在現(xiàn)代網(wǎng)絡(luò)瀏覽器中的新型代碼,并且提供新的性能特性和效果
W3C WebAssembly Community Group 開發(fā)的一項網(wǎng)絡(luò)標(biāo)準(zhǔn),對于瀏覽器而言,WebAssembly 提供了一條途徑,讓各種語言編寫的代碼以接近原生的速度在 Web 中運行。在這種情況下,以前無法以此方式運行的客戶端軟件等都將可以運行在 Web 中。
WebAssembly 設(shè)計之初就決定和 JavaScript 一起協(xié)同運行 —— 通過 JavaScript 中的 WebAssembly API,可以把 WebAssembly 模塊加載到一個 JavaScript 應(yīng)用中并且在兩者之間互相調(diào)用。這樣可以在同一個應(yīng)用中使用 WebAssembly 的高性能及 JavaScript 的高靈活性。
2 為什么需要 WebAssembly?
眾所周知 JavaScript 是解釋型語言,相比于編譯型語言需要在運行時轉(zhuǎn)換,所以解釋型語言的執(zhí)行速度要慢于編譯型語言。
編譯型語言和解釋型語言代碼執(zhí)行的具體流程如下:

因為解釋型語言每次執(zhí)行都需要把源碼轉(zhuǎn)換一次才能執(zhí)行,而轉(zhuǎn)換過程非常耗費時間和性能,也就導(dǎo)致在 JavaScript 背景下,web 無法執(zhí)行一些高性能應(yīng)用,如圖片剪輯、視頻剪輯、3D 游戲等。
根據(jù) MDN 的定義,WebAssembly 是一種運行在現(xiàn)代網(wǎng)絡(luò)瀏覽器中的新型代碼,并且提供新的性能特性和效果。可以在現(xiàn)代的網(wǎng)絡(luò)瀏覽器中運行 - 它是一種低級的類匯編語言,具有緊湊的二進制格式,可以接近原生的性能運行,并為諸如 C / C ++ 等語言提供一個編譯目標(biāo),以便它們可以在 Web 上運行。它也被設(shè)計為可以與 JavaScript 共存,允許兩者一起工作。
3 WebAssembly 的工作原理
WebAssembly 不被解釋,而是由開發(fā)者提前編譯為 WebAssembly 二進制格式,如下圖所示。由于變量類型都是預(yù)知的,因此瀏覽器加載 WebAssembly 文件時,JavaScript 引擎無須監(jiān)測代碼。它可以簡單地將這段代碼的二進制格式編譯為機器碼。

如果將每種編程語言都直接編譯為機器碼的各個版本,那么效率會很低。編譯器中稱為前端的部分會將所編寫的代碼編譯為一種中間表示 (intermediate representation,IR)。創(chuàng)建好 IR 代碼后,編譯器的后端部分會接收 IR 代碼,對其進行優(yōu)化,然后將其轉(zhuǎn)換為所需要的機器碼。

由于瀏覽器可以在若干不同的處理器 (比如桌面計算機、智能手機和平板設(shè)備) 上運行,因此為每個可能的處理器發(fā)布一個 WebAssembly 代碼的編譯后版本會非常繁復(fù)。替代方法即取得 IR 代碼,并通過一個專門的編譯器來運行,這個編譯器將 IR 代碼轉(zhuǎn)換為一種專用字節(jié)碼并放入后綴為.wasm 的文件中。此時 wasm 文件中的字節(jié)碼還不是機器碼,它只是支持 WebAssembly 的瀏覽器能夠理解的一組虛擬指令。當(dāng)加載到支持 WebAssembly 的瀏覽器中時,瀏覽器會驗證這個文件的合法性,然后這些字節(jié)碼會繼續(xù)編譯為瀏覽器所運行的設(shè)備上的機器碼。如下圖


WebAssembly 被設(shè)計為 JavaScript 的一個組件,不是它的替代品。雖然有些開發(fā)者試圖只用 WebAssembly 來創(chuàng)建整個網(wǎng)站,但這不是普遍情況。一般情況 JavaScript 仍然是更好的選擇。
4 WebAssembly 模塊內(nèi)部

模塊中不同段的含義說明:


編譯器負責(zé)生成 WebAssembly 模塊的段,并將它們按照適當(dāng)順序放置。
所有的段都是可選的,因此可能存在空模塊。
如果指定了已知段,那么它們只能出現(xiàn)一次并且要按照特定順序出現(xiàn)。
自定義段可以放置在已知段之前、之間或之后,用于指定不適用已知段的數(shù)據(jù)。
5 哪些語言可用來創(chuàng)建 WebAssembly 模塊?
現(xiàn)在 WebAssembly 的最小可行性版本(Minimum Viable Product,MVP)還沒有垃圾回收(garbage collection,GC),他限制了一些語言的使用。GC 作為一種后 MVP 功能正在開發(fā)中,實現(xiàn)之前,有幾種語言正在試驗 WebAssembly 支持,方式是將自己的 VM 編譯到 WebAssembly,或者在某些情況下將自己的垃圾回收器包含進去。
以下語言正在試驗或已經(jīng)完成 WebAssembly 支持:
C 和 C++
Rust 正致力于成為 WebAssembly 的首選編程語言。
AssemblyScript 是一種新編譯器,它用來將 TypeScript 轉(zhuǎn)換為 WebAssembly。
TeaVM 是一個將 Java 轉(zhuǎn)譯到 JavaScript 的工具,現(xiàn)在也可以生成 WebAssembly 了。
Go 1.11 為 WebAssembly 增加了一個試驗性項目,其編譯后的 WebAssembly 模塊包含一個垃圾回收器。
Pyodide 是 Python 的一個項目,其中包含了 Python 科學(xué)棧的核心包:Numpy、Pandas 和 matplotlib。
Blazor 是微軟的實驗性項目,用于將 C# 引入 WebAssembly。
更多列表關(guān)注 github: WebAssembly 支持列表
相關(guān)案例:
TeaVM:它可以將 JVM 字節(jié)碼翻譯成 JavaScript 和 WebAssembly
我們有一段時間后端開始做一些前端開發(fā),但是結(jié)果有時并不盡如人意,關(guān)鍵就在于我們的后端開發(fā)人員對前端無論是框架還是語法還是規(guī)范,都不是非常了解。這是在所難免的,但是因為業(yè)務(wù)需要又不得不做。
TeaVM 就為我們這種情況提供了一種解決方案,我們的后端開發(fā)人員依然使用自己熟悉的語言(java)進行開發(fā)。功能開發(fā)完成后再將_.class 或_.jar 文件通過 TeaVM 編譯成 wasm 或 JavaScript 供瀏覽器加載調(diào)用。
git:https://github.com/konsoletyper/teavm
官網(wǎng):https://teavm.org/
6 WebAssembly 可以用在哪?
目前大多數(shù)瀏覽器廠商都已經(jīng)支持 WebAssembly,包括 Chrome、Edge、Firefox 和 Safari。移動端 Web 瀏覽器也同樣支持。Node.js 也從版本 8 開始支持。
WebAssembly 不是 JavaScript 的替代品,而是它的一個補充,有些情況下 WebAssembly 是更好的選擇,有些情況下使用 JavaScript 會是一個更優(yōu)的方案。與 JavaScript 在同一個 VM 運行可讓兩種技術(shù)相輔相成。
WebAssembly 為非 JavaScript 的開發(fā)者提供了一個新的道路,幫助他們在 web 中使用自己編寫的代碼。也讓不了解 C 或 C++ 等語言的 web 開發(fā)者可與訪問更新、更快的庫。個人理解 WebAssembly 也可用來優(yōu)化某些庫的執(zhí)行速度。
6.1 一些使用 webAssembly 的案例
Figma — 基于瀏覽器的多人實時協(xié)作 UI 設(shè)計工具:https://www.figma.com/
Google Earth https://earth.google.com/ - 17 年開始支持在 FireFox 打開,主要依賴 webAssembly。之前使用 Native Client 導(dǎo)致只能在 chrome 中運行
Magnum — 跨平臺的 OpenGL 圖形引擎 https://github.com/mosra/magnum
Egret Engine - 一款 HTML5 游戲引擎 https://github.com/egret-labs/egret-core/
Web-DSP — 使用瀏覽器就能即時制作多媒體影音特效 https://github.com/shamadee/web-dsp
7 WebAssembly 怎么用?
7.1 得到 wasm 文件手動引入
var importObject = {
imports: {
imported_func: function(arg) {
console.log(arg);
}
}
};
// 輸出 42
fetch('simple.wasm')
.then(res =>
res.arrayBuffer()
).then(bytes =>
WebAssembly.instantiate(bytes, importObject)
).then(results => {
results.instance.exports.exported_func();
});


7.2 得到編譯好的 npm 包引入執(zhí)行
// alert(`Hello, ${name}`)
const js = import("./node_modules/@jdl/hello-wasm/hello_wasm.js");
js.then(js => {
js.greet("WebAssembly");
});

以下為 hello_wasm.js 文件編譯前源碼
// rust
extern crate wasm_bindgen;
use wasm_bindgen::*;
#[wasm_bindgen]
extern {
pub fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
本文從為什么需要 WebAssembly、WebAssembly 的工作原理、哪些語言可用來創(chuàng)建 WebAssembly 模塊、WebAssembly 可以用在哪里 以及 怎么使用 幾方面簡要介紹了 webAssembly。如果之前沒有了解過 webAssembly,可以做一些簡要的了解。
審核編輯:湯梓紅
-
Web
+關(guān)注
關(guān)注
2文章
1304瀏覽量
74460 -
瀏覽器
+關(guān)注
關(guān)注
1文章
1043瀏覽量
37076 -
C++
+關(guān)注
關(guān)注
22文章
2123瀏覽量
77110 -
代碼
+關(guān)注
關(guān)注
30文章
4967瀏覽量
73960 -
javascript
+關(guān)注
關(guān)注
0文章
526瀏覽量
56321
原文標(biāo)題:初探webAssembly
文章出處:【微信號:OSC開源社區(qū),微信公眾號:OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
WebAssembly技術(shù)_編譯ffmpeg(ubuntu20.04)
WebAssembly的起源及實踐分析
關(guān)于Mozilla讓WebAssembly并行啟動
.NET應(yīng)用程序可以直接調(diào)用WebAssembly模塊了
使用WebAssembly的網(wǎng)站大都用于加密貨幣挖掘和在線游戲
WebAssembly中的BL602/BL604模擬器使用
WebAssembly技術(shù)_編譯ffmpeg(ubuntu)
WebAssembly_Web運行CC++程序(win10)
介紹WebAssembly現(xiàn)存的一些風(fēng)險和他們的應(yīng)對方法
什么是WebAssembly(Wasm)?Wasm 與 Docker 的關(guān)系是什么
淺析Wasm-bpf架起Webassembly和eBPF內(nèi)核可編程的橋梁
在WebAssembly中使用Rust編寫eBPF程序并發(fā)布OCI鏡像
重新構(gòu)想前端開發(fā)!Kotlin推出新功能
基于WebAssembly構(gòu)建Web端音視頻通話引擎
WebAssembly是什么?為什么需要WebAssembly?WebAssembly的工作原理
評論