第一次听到 WebAssembly 的是来自于同事,他描述了一种不通过 JavaScript
编程语言也能够实现前端开发的方式。刚听到的时候很惊艳,想到前端开发竟然可以避开JavaScript
,简直神乎其技,但究竟如何实现的,又感觉很模糊。
最近总是听到 WebAssembly
,网上总是在描述它是浏览器中 JavaScript
的替代品。并且能够提供比 JavaScript
更高的性能诸如此类的话题。由于这个类说了又好像没有说的话,导致我对这个概念很模糊。今天抽空做了解。
WebAssembly
WebAssembly/wasm WebAssembly 或者 wasm 是一个可移植、体积小、加载快并且兼容 Web 的全新格式
^来源:WebAssembly 中文网
WebAssembly是一种新的编码方式,可以在现代的网络浏览器中运行 - 它是一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生的性能运行,并为诸如C / C ++等语言提供一个编译目标,以便它们可以在Web上运行。它也被设计为可以与JavaScript共存,允许两者一起工作。
^来源:WebAssembly MDN
WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.
^来源:WebAssembly
不同于JavaScript
的解释执行,WebAssembly
使得浏览器能够以二进制格式运行代码。由于更接近于汇编语言,所以在网络中传输效率和执行效率都比JavaScript
要高。但是另一方面由于WebAssembly
是一种紧凑的二进制格式,因此我们无法直接编写WebAssembly
代码,而是需要借助其他语言如(C、C++、Rust)等编程语言借助工具后编译为 WebAssembly
语言后才能使用。
了解到这里,WebAssembly 给我的感觉就像是在浏览器上运行的 JVM。它将原本在浏览器上JavaScript
直接解释执行在 JavaScript
虚拟机上的这个流程打破了,然后在中间像 Java
一样加了一层。
有什么好处呢?
首先,编译后的二进制文件要远远比源代码小,这就会使得请求.wasm
文件要比请求.js
文件速度要快;
另一方面,浏览器在执行二进制文件时可以避免解释执行的步骤,从而使得执行速度大大提升。可以类比 Java 程序执行速度没有C程序的执行速度高,原理是一样的。
但是,这样做带来的问题也很明显,编译后的代码不易于调试,而且由于中间多了一道供需,使得代码出错的几率也相对提高了。
除此之外 WebAssembly
还是给我们提供了另外一种可能,是 JavaScript
之外的更多的可能性。
环境准备
git
,ubuntu下apt install git
安装cmake
, ubuntu下 apt install cmake
安装gcc
, ubuntu下 apt install gcc
安装python
,ubuntu 下 apt install python
安装安装完成后,确认 git
,cmake
和 python
已经在你的环境变量中可以使用。
安装 Emscription
通过 git
克隆 Emscripten
仓库,然后执行命令即可完成安装:
> git clone https://github.com/emscripten-core/emsdk.git
# 国内环境可以使用镜像
# git clone https://gitclone.com/github.com/emscripten-core/emsdk.git
> cd emsdk
# 安装 emsdk
> ./emsdk install latest
# 激活 emsdk
> ./emsdk activate latest
# 配置环境变量
> source ./emsdk_env.sh
注意安装过程需要 git
、cmake
、gcc
等工具,如果这些工具在系统中缺失的话会导致一些错误;此外在安装成功后需要激活一下 emsdk
对应的模块,并配置环境变量,如果没有执行 source ./emsdk_env.sh
配置环境变量的话,在执行下面操作的时候可能会抛出一些变量未定义的错误。
# 在 emsdk 目录下
> mkdir -p emscripten/main binaryen/main
> git clone https://github.com/WebAssembly/binaryen.git binaryen/main
# 国内环境可以使用镜像
# git clone https://gitclone.com/github.com/WebAssembly/binaryen.git binaryen/main
> git clone https://github.com/emscripten-core/emscripten.git emscripten/main
# git clone https://gitclone.com/github.com/emscripten-core/emscripten.git emscripten/main
./emsdk install binaryen-main-64bit emscripten-main-64bit
上面克隆的这两个仓库是 emsdk 的子模块,其中 binaryen
是一个构件工具,而 emscrpten
是 JavaScript
的构件工具,如果我们直接执行 emsdk install
的话 emsdk
会直接去 github
上面克隆这两个仓库供我们使用。但由于网络延迟问题,直接从 github
上面克隆仓库的效率其实并不高,因此我们可以先通过镜像将仓库克隆下来,然后在执行 emsdk install
这样速度会快的多。
> emsdk activate binaryen-main-64bit emscripten-main-64bitt
> source ./emsdk_env.sh
# 配置环境变量
最后在安装完成后我们可以通过 emsdk
激活这两个模块,注意在激活后需要通过 source ./emsdk_env.sh
重新配置下环境变量,否则后续的操作有可能会抛出变量未定义的错误。
上面步骤完成后,我们的环境就基本配置好了,接下来我们可以尝试编写一个c文件,然后用emcc
进行编译:
// hello.c
#include
int main(){
printf("hello world\n");
return 0;
}
在代码文件 hello.c
编写完成后,执行脚本进行编译:
emcc hello.c -s WASM=1 -o hello.html
在命令执行完成后,当前目录中会多出一些文件,这些分别是编译后的文件产物:
最后,我们可以通过 emrun
指定当前目录来打开一个浏览器查看执行结果:
emrun --no_browser --port 8082 .
打开浏览器,查看执行结果:
或者,我们可以通过 node 执行 hello.js
,同样能够得到结果:
> node hello.js
hello world
之前看 阮一峰的博客和 WebAssembly 中文中,有部分入门教程和 github
上 emsdk
的操作出现了出入,大概是 emsdk
升级导致操作逻辑发生了改变,需要注意。
asm.js 和 Emscripten 入门教程
cmake官网
WebAssembly中文网
introducing_emscripten
WebAssembly官网
Rust
Rust 标准库
编译 Rust 为 WebAssembly
WebAssembly
学习LLVM第1篇:官方入门教程笔记
LLVM:模块化和可重用的编译器和工具链技术的集合
教程简介与词法分析器
WebAssembly
emsdk
emsdk文档
WebAssembly 开发者引导