WebAssembly 有一套完整的语义,实际上 wasm 是体积小且加载快的二进制格式, 其目标就是充分发挥硬件能力以达到原生执行效率
WebAssembly 运行在一个沙箱化的执行环境中,甚至可以在现有的 JavaScript 虚拟机中实现。在web环境中,WebAssembly 将会严格遵守同源策略以及浏览器安全策略。
WebAssembly 在 web 中被设计成无版本、特性可测试、向后兼容的。WebAssembly 可以被 JavaScript 调用,进入 JavaScript 上下文,也可以像 Web API 一样调用浏览器的功能。当然,WebAssembly 不仅可以运行在浏览器上,也可以运行在非web环境下。
WebAssembly支持多种语言
目前能编译成 WebAssembly 字节码的高级语言有:
AssemblyScript:语法和 TypeScript 一致,对前端来说学习成本低,为前端编写 WebAssembly 最佳选择;
c\c++:官方推荐的方式。
Rust:语法复杂、学习成本高,对前端来说可能会不适应。
Kotlin:语法和 Java、JS 相似,语言学习成本低。
Golang:语法简单学习成本低。但对 WebAssembly 的支持还处于未正式发布阶段。
开发环境搭建
安装WebAssembly for Rust 环境
安装Rust
移步到
www.rust-lang.org/tools/insta…
哦~
想要把 Rust 编译成 WebAssembly 需要一个工具: wasm-pack 。使用 wasm-pack 可以一条命令转成 WebAssembly 。
使用下面命令下载和安装:
bash cargo install wasm-pack
安装 wasm-pack 有坑
Ubuntu上可能会缺少依赖
installed libssl-dev on ubuntu 18 and still get this error:
error: failed to run custom build command for openssl-sys v0.9.39
process didn
复制代码
可能需要安装:
sudo apt install pkg-config
sudo apt install libssl-dev
复制代码
来写点 Rust
新建 Rust 项目,本文以斐波那契数列为例
cargo new --lib hello-wasm-fibonacci
创建成功后提示: Created library
hello-wasm-fibonacci
package
项目结构:
├── Cargo
.toml
└──
src
└── lib
.rs
1
directory,
2
files
复制代码
配置Cargo.toml
[package]
name = "hello-wasm"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
description = "A sample project with wasm-pack"
license = "MIT/Apache-2.0"
repository = "https://github.com/yourgithubusername/hello-wasm"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
复制代码
终于可以开始写 Rust 代码
(本文不展开 Rust 语法,专注 WebAssembly for Rust)
删除原来 lib.rs 的所有代码,在里面写想要的东西
extern
crate
wasm_bindgen;
use
wasm_bindgen::prelude::*;
fn
fibonacci
(n:
u32
)
->
u32
{
if
n ==
0
{
return
0
;
}
else
if
n ==
1
{
return
1
;
}
else
{
return
fibonacci
(n -
1
) +
fibonacci
(n -
2
);
#[wasm_bindgen]
pub
fn
get_fibonacci
(n:
u32
)
->
u32
{
return
fibonacci
(n);
复制代码
小问号你是否有很多朋友?
在 Rust 当中,库被称为 “crates”,因为我们使用的是一个外部库,所以有 "extern"
use xxx ::nnn::*;
是将库中的代码引入到你的代码中的使用命令。在这个情况下,将会引入 xxx::nnn 的全部模块
在 #[] 中的内容叫做 "属性",并以某种方式改变下面的语句,类似于Typescript或者Java里面的注解。这里使用#[wasm_bindgen]属性,就可以把 Rust 函数开放给 JavaScript 使用。
打包发布到 npm
使用 wasm-pack 构建 WebAssembly
wasm-pack build --scope mynpmusername
登录 npm (默认已安装 npm )
npm adduser
Username: yournpmusername
Password:
Email: (this IS public) you@example.com
复制代码
进入 WebAssembly 文件目录 pkg
cd pkg
由于 wasm-pack 生成的 package.js 漏了_bg.js ,需要修改package.json补充
"name"
:
"@mynpmusername/hello-wasm-fibonacci"
,
"collaborators"
:
[
"yourgitname <yourgitmail>"
"version"
:
"0.1.0"
,
"files"
:
[
"hello_wasm_fibonacci_bg.wasm"
,
"hello_wasm_fibonacci.js"
,
"hello_wasm_fibonacci_bg.js"
,
"hello_wasm_fibonacci.d.ts"
"module"
:
"hello_wasm_fibonacci.js"
,
"types"
:
"hello_wasm_fibonacci.d.ts"
,
"sideEffects"
:
false
复制代码
发布到npm
npm publish --access=public
在前端项目中使用
新建前端项目
mkdir web
新建 package.json
"scripts"
: {
"serve"
:
"webpack-dev-server"
"dependencies"
: {
"@mynpmusername/hello-wasm-fibonacci"
:
"^0.1.0"
"devDependencies"
: {
"webpack"
:
"^4.25.1"
,
"webpack-cli"
:
"^3.1.2"
,
"webpack-dev-server"
:
"^3.1.10"
复制代码
新建webpack.config.js
const path = require('path');
module.exports = {
entry: "./index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "index.js",
mode: "development"
复制代码
index.htm
<!DOCTYPE html>
<meta charset="utf-8">
<title>hello-wasm example</title>
</head>
<script src="./index.js"></script>
</body>
</html>
复制代码
index.js
const fibonacci = import("./node_modules/@yournpmusername/hello-wasm-fibonacci/hello_wasm_fibonacci.js")
fibonacci.then(fibonacci => {
const a = fibonacci.get_fibonacci(10)
console.log(a)
复制代码
AssemblyScript
typescript 编写 wasm
yarn init -y
yarn add @assemblyscript/loader
yarn add assemblyscript -D
npx asinit .
yarn asbuild or yarn asbuild:watch
"scripts"
:
{
"asbuild:untouched"
:
"asc assembly/index.ts -b build/untouched.wasm -t build/untouched.wat --validate --sourceMap --debug"
,
"asbuild:optimized"
:
"asc assembly/index.ts -b build/optimized.wasm -t build/optimized.wat --validate --sourceMap --optimize"
,
"asbuild"
:
"npm run asbuild:untouched && npm run asbuild:optimized"
,
"asbuild:watch"
:
"onchange -i 'assembly/**/*' -- npm run asbuild"
需要用 onchange库实现开发模式
复制代码
tsconfig.json 配置
"extends"
:
"../node_modules/assemblyscript/std/assembly.json"
,
"include"
:
[
"./**/*.ts"
复制代码
开发方式类似于 ts
export function add(a: i32, b: i32): i32 {
return a + b;
export function isPrime(x: u32): bool {
if (x < 2) {
return false;
for (let i: u32 = 2; i < x; i++) {
if (x % i === 0) {
return false;
return true;
export function fabonacci(n:number):number{
return n < 2 ? n : fabonacci(n - 1) + fabonacci(n - 2);
复制代码
总结
经过比较 TypeScript 生成的 wasm 速度比 Rust 快, Rust 打包出来的 wasm 比 TypeScrip 要小很多倍 (下次再详细写)
Rust 语言还需要学习
wasm 性能比 JS 要强很多, 可以应用在高性能需求场景。
wasm 目前打包工作流完善
相关Demo
DEMO 1
DEMO 2
如果懒得配环境,又想试试 WebAssembly
可以直接用
webassembly.studio/