來源 | OSCHINA 社區(qū)
作者 | 京東云開發(fā)者-京東物流 潘維高
1 WebAssembly 是什么?
一種運(yùn)行在現(xiàn)代網(wǎng)絡(luò)瀏覽器中的新型代碼,并且提供新的性能特性和效果
W3C WebAssembly Community Group 開發(fā)的一項(xiàng)網(wǎng)絡(luò)標(biāo)準(zhǔn),對(duì)于瀏覽器而言,WebAssembly 提供了一條途徑,讓各種語言編寫的代碼以接近原生的速度在 Web 中運(yùn)行。在這種情況下,以前無法以此方式運(yùn)行的客戶端軟件等都將可以運(yùn)行在 Web 中。
WebAssembly 設(shè)計(jì)之初就決定和 JavaScript 一起協(xié)同運(yùn)行 —— 通過 JavaScript 中的 WebAssembly API,可以把 WebAssembly 模塊加載到一個(gè) JavaScript 應(yīng)用中并且在兩者之間互相調(diào)用。這樣可以在同一個(gè)應(yīng)用中使用 WebAssembly 的高性能及 JavaScript 的高靈活性。
2 為什么需要 WebAssembly?
眾所周知 JavaScript 是解釋型語言,相比于編譯型語言需要在運(yùn)行時(shí)轉(zhuǎn)換,所以解釋型語言的執(zhí)行速度要慢于編譯型語言。
編譯型語言和解釋型語言代碼執(zhí)行的具體流程如下:
因?yàn)榻忉屝驼Z言每次執(zhí)行都需要把源碼轉(zhuǎn)換一次才能執(zhí)行,而轉(zhuǎn)換過程非常耗費(fèi)時(shí)間和性能,也就導(dǎo)致在 JavaScript 背景下,web 無法執(zhí)行一些高性能應(yīng)用,如圖片剪輯、視頻剪輯、3D 游戲等。
根據(jù) MDN 的定義,WebAssembly 是一種運(yùn)行在現(xiàn)代網(wǎng)絡(luò)瀏覽器中的新型代碼,并且提供新的性能特性和效果??梢栽诂F(xiàn)代的網(wǎng)絡(luò)瀏覽器中運(yùn)行 - 它是一種低級(jí)的類匯編語言,具有緊湊的二進(jìn)制格式,可以接近原生的性能運(yùn)行,并為諸如 C / C ++ 等語言提供一個(gè)編譯目標(biāo),以便它們可以在 Web 上運(yùn)行。它也被設(shè)計(jì)為可以與 JavaScript 共存,允許兩者一起工作。
3 WebAssembly 的工作原理
WebAssembly 不被解釋,而是由開發(fā)者提前編譯為 WebAssembly 二進(jìn)制格式,如下圖所示。由于變量類型都是預(yù)知的,因此瀏覽器加載 WebAssembly 文件時(shí),JavaScript 引擎無須監(jiān)測(cè)代碼。它可以簡(jiǎn)單地將這段代碼的二進(jìn)制格式編譯為機(jī)器碼。
如果將每種編程語言都直接編譯為機(jī)器碼的各個(gè)版本,那么效率會(huì)很低。編譯器中稱為前端的部分會(huì)將所編寫的代碼編譯為一種中間表示 (intermediate representation,IR)。創(chuàng)建好 IR 代碼后,編譯器的后端部分會(huì)接收 IR 代碼,對(duì)其進(jìn)行優(yōu)化,然后將其轉(zhuǎn)換為所需要的機(jī)器碼。
由于瀏覽器可以在若干不同的處理器 (比如桌面計(jì)算機(jī)、智能手機(jī)和平板設(shè)備) 上運(yùn)行,因此為每個(gè)可能的處理器發(fā)布一個(gè) WebAssembly 代碼的編譯后版本會(huì)非常繁復(fù)。替代方法即取得 IR 代碼,并通過一個(gè)專門的編譯器來運(yùn)行,這個(gè)編譯器將 IR 代碼轉(zhuǎn)換為一種專用字節(jié)碼并放入后綴為.wasm 的文件中。此時(shí) wasm 文件中的字節(jié)碼還不是機(jī)器碼,它只是支持 WebAssembly 的瀏覽器能夠理解的一組虛擬指令。當(dāng)加載到支持 WebAssembly 的瀏覽器中時(shí),瀏覽器會(huì)驗(yàn)證這個(gè)文件的合法性,然后這些字節(jié)碼會(huì)繼續(xù)編譯為瀏覽器所運(yùn)行的設(shè)備上的機(jī)器碼。如下圖
WebAssembly 被設(shè)計(jì)為 JavaScript 的一個(gè)組件,不是它的替代品。雖然有些開發(fā)者試圖只用 WebAssembly 來創(chuàng)建整個(gè)網(wǎng)站,但這不是普遍情況。一般情況 JavaScript 仍然是更好的選擇。
4 WebAssembly 模塊內(nèi)部
模塊中不同段的含義說明:
編譯器負(fù)責(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ā)中,實(shí)現(xiàn)之前,有幾種語言正在試驗(yàn) WebAssembly 支持,方式是將自己的 VM 編譯到 WebAssembly,或者在某些情況下將自己的垃圾回收器包含進(jìn)去。
以下語言正在試驗(yàn)或已經(jīng)完成 WebAssembly 支持:
C 和 C++
Rust 正致力于成為 WebAssembly 的首選編程語言。
AssemblyScript 是一種新編譯器,它用來將 TypeScript 轉(zhuǎn)換為 WebAssembly。
TeaVM 是一個(gè)將 Java 轉(zhuǎn)譯到 JavaScript 的工具,現(xiàn)在也可以生成 WebAssembly 了。
Go 1.11 為 WebAssembly 增加了一個(gè)試驗(yàn)性項(xiàng)目,其編譯后的 WebAssembly 模塊包含一個(gè)垃圾回收器。
Pyodide 是 Python 的一個(gè)項(xiàng)目,其中包含了 Python 科學(xué)棧的核心包:Numpy、Pandas 和 matplotlib。
Blazor 是微軟的實(shí)驗(yàn)性項(xiàng)目,用于將 C# 引入 WebAssembly。
更多列表關(guān)注 github: WebAssembly 支持列表
相關(guān)案例:
TeaVM:它可以將 JVM 字節(jié)碼翻譯成 JavaScript 和 WebAssembly
我們有一段時(shí)間后端開始做一些前端開發(fā),但是結(jié)果有時(shí)并不盡如人意,關(guān)鍵就在于我們的后端開發(fā)人員對(duì)前端無論是框架還是語法還是規(guī)范,都不是非常了解。這是在所難免的,但是因?yàn)闃I(yè)務(wù)需要又不得不做。
TeaVM 就為我們這種情況提供了一種解決方案,我們的后端開發(fā)人員依然使用自己熟悉的語言(java)進(jìn)行開發(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。移動(dòng)端 Web 瀏覽器也同樣支持。Node.js 也從版本 8 開始支持。
WebAssembly 不是 JavaScript 的替代品,而是它的一個(gè)補(bǔ)充,有些情況下 WebAssembly 是更好的選擇,有些情況下使用 JavaScript 會(huì)是一個(gè)更優(yōu)的方案。與 JavaScript 在同一個(gè) VM 運(yùn)行可讓兩種技術(shù)相輔相成。
WebAssembly 為非 JavaScript 的開發(fā)者提供了一個(gè)新的道路,幫助他們?cè)?web 中使用自己編寫的代碼。也讓不了解 C 或 C++ 等語言的 web 開發(fā)者可與訪問更新、更快的庫(kù)。個(gè)人理解 WebAssembly 也可用來優(yōu)化某些庫(kù)的執(zhí)行速度。
6.1 一些使用 webAssembly 的案例
Figma — 基于瀏覽器的多人實(shí)時(shí)協(xié)作 UI 設(shè)計(jì)工具:https://www.figma.com/
Google Earth https://earth.google.com/ - 17 年開始支持在 FireFox 打開,主要依賴 webAssembly。之前使用 Native Client 導(dǎo)致只能在 chrome 中運(yùn)行
Magnum — 跨平臺(tái)的 OpenGL 圖形引擎 https://github.com/mosra/magnum
Egret Engine - 一款 HTML5 游戲引擎 https://github.com/egret-labs/egret-core/
Web-DSP — 使用瀏覽器就能即時(shí)制作多媒體影音特效 https://github.com/shamadee/web-dsp
7 WebAssembly 怎么用?
7.1 得到 wasm 文件手動(dòng)引入
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 可以用在哪里 以及 怎么使用 幾方面簡(jiǎn)要介紹了 webAssembly。如果之前沒有了解過 webAssembly,可以做一些簡(jiǎn)要的了解。
審核編輯:湯梓紅
-
Web
+關(guān)注
關(guān)注
2文章
1287瀏覽量
71291 -
瀏覽器
+關(guān)注
關(guān)注
1文章
1040瀏覽量
36251 -
C++
+關(guān)注
關(guān)注
22文章
2119瀏覽量
75180 -
代碼
+關(guān)注
關(guān)注
30文章
4898瀏覽量
70590 -
javascript
+關(guān)注
關(guān)注
0文章
525瀏覽量
54743
原文標(biāo)題:初探webAssembly
文章出處:【微信號(hào):OSC開源社區(qū),微信公眾號(hào):OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
WebAssembly技術(shù)_編譯ffmpeg(ubuntu20.04)

WebAssembly的起源及實(shí)踐分析

關(guān)于Mozilla讓WebAssembly并行啟動(dòng)

.NET應(yīng)用程序可以直接調(diào)用WebAssembly模塊了
使用WebAssembly的網(wǎng)站大都用于加密貨幣挖掘和在線游戲

WebAssembly中的BL602/BL604模擬器使用
WebAssembly技術(shù)_編譯ffmpeg(ubuntu)

WebAssembly_Web運(yùn)行CC++程序(win10)
介紹WebAssembly現(xiàn)存的一些風(fēng)險(xiǎn)和他們的應(yīng)對(duì)方法
什么是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端音視頻通話引擎

評(píng)論