WebAssembly 进移动应用 — 一份逻辑,两端原生¶
1. 这一章讲什么¶
移动开发的老痛点:Android 一套(Java/Kotlin)、iOS 一套(Swift/Objective-C), 性能要原生就得双倍维护。React Native/Flutter 解决了 UI 层共享, 但计算密集的任务在 JS/Dart 里还是慢。这一章的位置:Wasm 只接管逻辑层—— 图像滤镜、加密、压缩、小模型推理写成一份模块,两端嵌;UI 照旧各端原生。 这是「Wasm 出浏览器」路线图上最后一站(设备侧)。1
2. 顶层全景¶
写一次:Rust / C++ / AssemblyScript → .wasm
│
├── React Native:JS 层 instantiateStreaming(Metro 要认 .wasm)
├── Flutter:编译成 .so/.dylib → dart:ffi 直调
├── Android 原生:WebView,或 JNI 加载 .so(System.loadLibrary)
└── iOS 原生:WKWebView,或 Wasmer 嵌入 + FFI(dlopen/dlsym)
│
▼
界面不动:Jetpack Compose / SwiftUI / RN / Flutter 照旧
图说:四个落点一个产物;选择落点 = 选择「离原生多近」。
3. 核心原理¶
3.1 价值主张,一句话四层¶
- 逻辑统一:性能模块一份,Android/iOS 行为一致,更新只换
.wasm; - 近原生速度:AOT 编译,压过 RN 的 JS 和 Flutter 的 Dart 热路径;
- 界面不动:Wasm 不碰 UI,互补而非替代;
- 多语言:Rust(安全)、C/C++(老库复用,如 OpenCV)、AssemblyScript(JS 开发者友好)。2
3.2 四个落点,各怎么接¶
React Native:引擎是 JavaScriptCore(iOS 系 RN 的默认 JS 引擎),
支持 Wasm,所以 Web 那套 instantiateStreaming(fetch('module.wasm')) 基本照搬。
两个工程细节:Metro 打包器要配置认 .wasm(metro.config.js 里加
assetExts: ['wasm']),文件读取靠 react-native-fs。
短板书里没藏:JavaScriptCore 的 SIMD 和多线程支持不全,要换 V8 系引擎才行。3
Flutter:Dart 没有原生 Wasm 执行,正路是编译成共享库(.so Android /
.dylib iOS),dart:ffi 直调——书里的例子五行讲透:4
final dylib = DynamicLibrary.open('libwasm_math.so');
final add = dylib.lookupFunction<
Int32 Function(Int32, Int32), int Function(int, int)>('add');
print(add(2, 3)); // 5
lookupFunction 把 C 函数签名和 Dart 函数类型一一对应,没有中间桥。
复杂交互走 platform channel(Dart ↔ 原生代码的通用消息通道)。5
Android 原生:两条路。WebView 里跑(能跑,但隔了一层浏览器);
正经路是 JNI(Java Native Interface,Java/Kotlin 调原生代码的标准桥):
Rust 用 #[no_mangle] extern "C" 暴露 C 签名函数,经 NDK 编成 .so,
Java 侧 System.loadLibrary("wasm_math") 加载、public native int add(int, int) 声明后直接调。6
iOS 原生:WKWebView 里 evaluateJavaScript 跑 Wasm(书里的 Swift 例);
或者更原生:Wasmer 等运行时嵌进 App,经 FFI(外部函数接口)绑定,
dlopen/dlsym 那套 Unix 传统手艺。挑战两条:Android 碎片化(ARMv7/ARM64/x86_64
三套架构都要测)、iOS 沙箱严(系统资源基本不给,除非走原生绑定)。7
3.3 模块怎么造¶
Rust 流程(书里的完整步骤):cargo new wasm_math --lib →
#[wasm_bindgen] pub fn add(a: i32, b: i32) -> i32 → wasm-pack build --target web
出 .wasm + JS 胶水;要更深集成时,不走 Wasm 产物而是直接编共享库——
Rust 编译 Android .so / iOS .dylib,用 cbindgen 生成 C 头文件给 JNI/FFI 用,
wasm-opt 压体积。8
这个细节值得停一下:移动端经常跳过了 .wasm 这一步,直接上原生库 ——因为目标平台已知,不需要 Wasm 的可移植层。Wasm 在这里的价值退化为 「开发期的可移植与测试载体」和「逻辑统一的中立格式」。书里两种都讲,没替你选。
3.4 优化与用例¶
移动端优化五招:SIMD(std::simd / Emscripten intrinsics)、多线程
(移动 JSC 普遍不支持,书里说得很实在)、模块缓存(编译结果存
AsyncStorage/SharedPreferences,免重复解析)、流式编译、AOT 预编译
(Lucet 把模块预编译成原生码,近零启动——实时视频剪辑这类场景用)。9
四个主力用例,每个都对应一组现成库:图像/视频处理(Rust 滤镜)、端上 AI 推理 (决策树(一层层 if-else 式分类)、k-NN 这类小模型)、密码学(SHA-256/签名/加密,沙箱加持)、 压缩(zstd/Brotli 编进 Wasm,上传前压)。10
3.5 主线例子:照片编辑应用(书里的真实场景走查)¶
一个跨平台照片 App,核心需求:高斯模糊、边缘检测、动态裁剪、上传前压缩。 (以下步骤是把本章机制组装成的完整走查;库名与接口出自原书。)
第 1 步:写模块。 Rust 实现滤镜与压缩,#[wasm_bindgen] 标出对外函数。11
第 2 步:双产物构建。 Web/RN 侧:wasm-pack build --target web 出
.wasm;原生侧:Rust 经 NDK 编 Android .so、Xcode 工具链编 iOS .dylib,
cbindgen 出头文件。12
第 3 步:两端接入。 RN 版走 JS instantiateStreaming;Flutter 版走
dart:ffi DynamicLibrary.open;原生版走 JNI / FFI。13
第 4 步:收益对账(书里的原话要点)。 两端行为一致;不送两份平台原生库,
包体更小;性能不减;更新只换 .wasm 或 .so,不用重新过审双端二进制。14
第 5 步:上线纪律。 wasm-opt 剥未用代码、模块按职责拆分(图像一个、加密一个)、
多架构全测、老 WebView 环境备 JS 兜底、.wasm 打进 assets 或走 HTTPS、CI 双端测。15
3.6 未来五条与工具¶
趋势:Wasm GC(让 Dart/JS 系语言进 Wasm)、移动原生运行时(Wasmer Mobile、 Lucet 嵌入,绕开 WebView)、云端 Wasm + 端上协同、WASI 上手机 (文件/网络能力)、两家 WebView 的 Wasm 支持持续变好(SIMD/线程)。16
工具认名字:wasmer-mobile(嵌入运行时)、wasm-bindgen(RN 胶水)、 wasm-pack、Emscripten、Binaryen、Lucet(AOT)。17
4. 作者的判断与证据¶
- 「RN 的 JavaScriptCore 支持 Wasm」:属实,但 SIMD/线程短板写得也属实,平衡;
- 「Wasm 模块显著小于两份原生库」:方向对(一份替代两份),「显著」无实测;
- 「iOS 严格沙箱限制 Wasm 系统访问」:准确;
- 工具一节的质量参差(把 ScyllaDB/PostgreSQL 列为「移动工具」), 是本书编辑粗糙的典型痕迹。
判断(我们的,不是书里的): 本章最诚实也最容易被读漏的一点,是 3.3 那个 「跳过 .wasm」的分叉:一旦目标平台固定为 Android+iOS,直接编共享库往往比 嵌入 Wasm 运行时更简单更快——Wasm 在移动端的真实卖点其实是 「逻辑的中立载体 + 跨端一致性」,而不是性能(性能上原生库不吃亏)。 如果错,会错在: 如果 Wasm GC 与 Component Model 成熟到「一份组件四端直跑、 免 FFI 胶水」,性能与体积的天平才会真正倒向 Wasm 产物——那是本章「未来趋势」 里押注的方向,落地时间未定。
5. 边界与局限¶
- 没有实测性能表:全书移动端零 benchmark,「near-native」始终是无数据断言;
- JS 引擎差异只说了一半:不同 RN 版本/不同厂商引擎的 Wasm 行为差异没有展开;
- Flutter 的 Wasm 官方路线(Dart 编译到 Wasm,WasmGC 落地后)未提,是重要遗漏;
- 更新分发只说「换二进制」,应用商店的审核与热更新政策约束没讲。
6. 可带走的¶
- 移动端 Wasm 的正确定位:逻辑层共享,UI 照旧原生;别拿它替 UI。
- 四个落点按「离原生远近」选:RN/Flutter 框架内 → WebView → JNI/FFI 原生。
- RN:Metro 认
.wasm+react-native-fs;JSC 无 SIMD/线程。 - Flutter:编译
.so/.dylib,dart:ffilookupFunction直调,复杂交互走 platform channel。 - Android JNI:
System.loadLibrary+public native声明;Rust 侧#[no_mangle] extern "C"。 - iOS:WKWebView 能跑但隔层;要原生用 Wasmer 嵌入 +
dlopen/dlsym。 - 平台固定时,直接编共享库可能比嵌 Wasm 运行时更简单——Wasm 的卖点转向「中立格式 + 一致性」。
- 优化五招:SIMD、线程(受限)、模块缓存、流式、AOT(Lucet)。
- 用例四件套:图像、端上小模型、密码学、压缩。
- 上线:多架构(ARMv7/ARM64/x86_64)、模块拆分、JS 兜底、CI 双端。
7. 原文地图¶
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 移动端问题与 Wasm 定位 | WebAssembly in Mobile Apps | text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:51(搜「separate codebases」) · text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:57(搜「write logic once」) |
| 集成点:JNI/NDK/FFI/WebView | 同上 | text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:253(搜「Java Native Interface」) |
| RN 配置与限制 | 同上 | text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:497(搜「assetExts」) · text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:555(搜「lack SIMD」) |
| Flutter dart:ffi 例 | 同上 | text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:601(搜「DynamicLibrary.open」) · text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:605(搜「Outputs 5」) |
| Android JNI 例 | 同上 | text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:785(搜「System.loadLibrary」) |
| iOS WKWebView 与 FFI | 同上 | text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:837(搜「evaluateJavaScript」) · text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:853(搜「dlopen/dlsym」) |
| 模块构建与 cbindgen | 同上 | text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:705(搜「--target web」) · text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:741(搜「cbindgen」) |
| 优化五招 | 同上 | text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:873(搜「SIMD Extensions」) · text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:911(搜「Lucet」) |
| 用例四件套 | 同上 | text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:931(搜「Image/Video Processing」) · text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:953(搜「zstd」) |
| 部署最佳实践 | 同上 | text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:973(搜「Module Size」) · text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:987(搜「ARMv7」) |
| 未来趋势 | 同上 | text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1045(搜「Future Trends」) |
-
出处:「WebAssembly in Mobile Apps」第 49–57 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:51,搜「separate codebases」)与text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:57(搜「write logic once」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 59–151 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:65,搜「performance-critical modules」)与text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:101(搜「logic layer」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 455–557 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:497,搜「assetExts」)与text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:555(搜「lack SIMD」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 559–623 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:601,搜「DynamicLibrary.open」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 607–623 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:607,搜「Platform Channels」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 755–809 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:785,搜「System.loadLibrary」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 811–865 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:853,搜「dlopen/dlsym」)与text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:863(搜「fragmented ecosystem」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 631–753 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:705,搜「--target web」)与text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:741(搜「cbindgen」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 867–923 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:911,搜「near-zero startup time」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 925–965 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:953,搜「zstd」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 423–447 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:433,搜「Gaussian blur」)。步骤编排为演示结构,机制与工具名均出自原书。 ↩ -
出处:「WebAssembly in Mobile Apps」第 723–735 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:729,搜「.dylib」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 165–175 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:169,搜「native bridge」)与text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:173(搜「platform channels」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 439–447 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:441,搜「Runs identically on Android and iOS」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 967–1043 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:985,搜「multiple architectures」)与text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1005(搜「JavaScript implementation」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 1045–1085 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1051,搜「Wasm GC」)与text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1059(搜「Wasmer Mobile」)。 ↩ -
出处:「WebAssembly in Mobile Apps」第 1087–1143 段(
text/23-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1117,搜「wasmer-mobile」)。 ↩