往浏览器转换器里拖入一张 HEIC 照片。它本质上是一种容器格式,里面封装着 HEVC 编码的图像数据——也就是 4K 视频所用的 H.265 压缩。浏览器没有内置的 HEVC 解码器,用 JavaScript 从头写一个会既慢又脆弱,而且体积庞大。真正需要的解码器是 libheif,一个由 strukturag 维护的 C++ 库。WebAssembly 正是让这套 C++ 解码器在浏览器标签页里跑起来的技术。
这一个例子已经道出了它的本质。WebAssembly 不是一门新的编程语言,也不是 JavaScript 的替代品。它是一种可移植的二进制指令格式,同时也是一个沙盒化执行环境,与 JavaScript 一同运行在浏览器中。
WebAssembly 到底是什么
WebAssembly(Wasm)是一项 W3C 标准。它定义了一种紧凑的二进制指令格式和一种基于栈的虚拟机。通常你不会手写 Wasm,而是从 C、C++、Rust、Go、Zig、C# 以及越来越多的其他语言编译得到。最终产物是一个 .wasm 模块,浏览器会下载、校验它,并在一个内存安全的沙盒中执行。
所有主流浏览器从 2017 年起就已支持 WebAssembly。该模块格式被设计为:
- 紧凑:二进制格式,解析速度比等效的 JavaScript 源码更快。
- 快速:由浏览器提前编译为机器码。
- 安全:每个模块拥有独立的线性内存,并带有边界检查。
- 语言无关:任何能生成 Wasm 指令集的语言都可以在 Web 上运行。
传统 Web 的局限
JavaScript 很适合编写用户界面、网络请求和胶水代码。它是动态类型、垃圾回收、JIT 编译的语言。这些特性让它很灵活,但也让它在重计算场景下表现不可预测。
垃圾回收暂停可能在动画中途冻结 UI 线程。JIT 预热意味着同一段代码在不同时刻可能以不同速度运行。对于数值或位运算类工作——图像解码、视频编码、密码学、物理模拟、大规模矩阵运算——JavaScript 往往比用 C 或 Rust 编译出的相同逻辑慢一个数量级。
另一项限制是生态锁定。数十年来积累的图像、音频、视频和科学计算库都是用 C 和 C++ 写成的。要把这些能力搬到 Web 上,用 JavaScript 重写并不现实。
WebAssembly 为什么存在
Wasm 的诞生是为了同时解决两个问题:
- 在浏览器中运行现有的原生代码,无需用 JavaScript 重写。
- 为 Web 应用提供一个可预测的高性能执行层,处理那些 JavaScript 本就不擅长的部分。
它明确是 JavaScript 的搭档,而不是继任者。DOM、网络栈和大多数 API 仍由 JavaScript 掌控。Wasm 负责隔离的计算,JavaScript 负责编排调度。
WebAssembly 能解决什么
- CPU 密集型任务:图像解码、视频转码、物理模拟、数据加密。
- 可预测的性能:没有垃圾回收器,也没有 JIT 预热曲线。
- 代码复用:把 libheif、FFmpeg、SQLite、OpenCV 等经受过实战检验的库带到浏览器中。
- 隐私:敏感数据可以在本地处理,而不用上传到服务器。
- 离线执行:
.wasm模块下载完成后,无需网络往返即可运行。
优势与局限
| 方面 | 优势 | 局限 |
|---|---|---|
| 性能 | 数值和内存密集型任务接近原生速度 | 不会比原生更快;仍受浏览器和设备限制 |
| 可移植性 | 一个模块可在任何浏览器和操作系统上运行 | 需要 JavaScript 宿主来操作 DOM 和大多数浏览器 API |
| 安全 | 带边界检查的沙盒线性内存 | 与任何浏览器代码一样,可能受到 Spectre 类侧信道攻击 |
| 生态 | 复用现有的 C/C++/Rust 代码库 | 与 JavaScript 互操作会增加复杂度和开销 |
| 启动 | 二进制解析速度快 | 首次加载时模块下载和实例化可能较大 |
客观的结论:Wasm 让浏览器能够完成以前做不到的工作,但它并没有消除运行在用户设备上所受到的约束。
常见用例
当 Web 应用需要在本地完成重负载工作时,WebAssembly 已成为默认选择:
- 图像与视频编辑:Figma、Photopea 等工具使用 Wasm 进行渲染和特效处理。
- 视频转码:FFmpeg.wasm 在浏览器内运行 FFmpeg,完成格式转换。
- 光学字符识别:Tesseract.js 将 Tesseract OCR 引擎移植到 Wasm。
- 游戏:Unity、Godot 和 Unreal Engine 都可以导出为 Wasm,用于浏览器游戏。
- 数据分析:Pyodide 带来 Python 和科学计算包;sql.js 在浏览器中运行 SQLite。
- 机器学习推理:ONNX Runtime Web 使用 Wasm 后端进行 CPU 推理。
- CAD 与 3D 查看器:过去只能在桌面运行的复杂几何内核。
- 密码学:哈希、加密和零知识证明在客户端执行。
常见的基于 WebAssembly 的库
| 库 | 来源 | 作用 |
|---|---|---|
| heic-to | 通过 Emscripten 编译的 libheif | 在浏览器中解码 HEIC/HEIF 图像,并转换为 JPEG、PNG 或位图。 |
| FFmpeg.wasm | 通过 Emscripten 编译的 FFmpeg | 完全在客户端进行音频/视频转码、复用和滤镜处理。 |
| Tesseract.js | 通过 Emscripten 编译的 Tesseract OCR | 在浏览器中识别图像中的文字。 |
| sql.js | 通过 Emscripten 编译的 SQLite | 在浏览器中使用内存文件运行完整的 SQLite 数据库引擎。 |
| Pyodide | 通过 Emscripten 编译的 CPython | 无需后端即可运行 Python 以及 NumPy、Pandas、SciPy 等包。 |
| ONNX Runtime Web | 通过 Emscripten 编译的 ONNX Runtime | 在 CPU(Wasm)或 GPU(WebGL/WebGPU)上执行 ONNX 机器学习模型。 |
表中每一项都是同一个套路:把成熟的原生项目编译成 Wasm,再包装成 JavaScript API。这正是 WebAssembly 在实践中的真正价值。
为什么在线 HEIC 转 JPG/PNG/WebP 需要 WebAssembly
HEIC 本质上是一种容器,不是编解码器。真正的图像数据使用 HEVC 编码,计算成本高且受专利限制。没有浏览器内置可供网页使用的原生 HEVC 解码器。服务器端转换是显而易见的备选方案,但它需要用户上传照片。
另一种方案是把 libheif——桌面工具使用的同款解码器——编译成 WebAssembly。当你使用我们的 HEIC 转 JPG 转换器 时,解码就在浏览器中完成:
- 读取
ftypbox 签名来验证文件。 - libheif Wasm 模块在本地解码 HEVC 码流。
- 解码后的位图被写入 canvas,并导出为 JPEG。
同一个模块也支持 HEIC 转 PNG,可输出带透明度的无损图像;以及 HEIC 转 WebP,用于经过 Web 优化的体积。无需上传,无需服务器处理,也没有第三方能看到图像。
这个工作流之所以成立,是因为 WebAssembly 能够运行真正的图像解码器。仅靠 JavaScript 无法在合理时间内解析 HEVC;上传到服务器又会破坏隐私承诺。Wasm 是让这一切成立的关键支撑。
WebAssembly 的未来
Wasm 正在走出浏览器。WebAssembly System Interface(WASI)定义了一套可移植的系统接口,让 Wasm 模块可以运行在服务器、边缘 Worker 和物联网设备上。Wasmtime、Wasmer 和 WasmEdge 等运行时已经在浏览器之外的生产环境中部署。
Component Model 提案将让 Wasm 模块暴露类型化接口并像库一样组合,从而更容易把 Rust 模块插到 Python 宿主或 Go 服务中。WebAssembly GC 则为 Java、Kotlin 等托管语言提供更好的支持。这些都不是要在浏览器中取代 JavaScript——而是要让 Wasm 成为一种通用、轻量的运行时目标。
浏览器内部也呈现同样的趋势:更多原生能力被移到客户端,更多保护隐私的工具出现,更多曾经只能在桌面运行的库也在标签页中跑了起来。WebAssembly 不是用户会注意到的抢眼功能,却正日益成为让复杂任务得以在 Web 上运行的关键。



