粗略翻译, 推荐看原文
https://auth0.com/blog/2015/10/14/7-things-you-should-know-about-web-assembly/了解 WebAssembly, 了解 Web 的将来
如果你不熟悉 WebAssembly 后面的概念, 可以读一下:
ArsTechnica 的 Peter Bright 写的优秀的论文 ,
或者是 Brendan Eich 在他的个人博客上写的公告文章考虑到本文的目标, 这里加上个简短的术语表:
源码(Source code): 开发者写的.
编译器(Compiler): 一个应用程序, 用于把源码转换为汇编,字节码或者机器码(任何其他的应用程序或者硬件可以运行的)
汇编(Assembly): 低级的类似源码的语言, 针对特定机器或特定应用程序
字节码(Bytecode): 低级的二进制的代码形式, 可以被其他应用程序执行
机器码(Machine code): 代码的二进制形式, 可以由硬件直接执行
WebAssembly 的目标是 Web 的字节码. 未来的开发者会这样使用 WebAssembly:
开发一个应用(源码用任何可以编译到 WebAssembly 的语言)
用编译器把源码转换到 WebAssembly 字节码(可能只要的话转化成汇编)
在浏览器加载字节码并执行
已经说过的再说一次: JavaScript 依然会继续
得益于 Web 平台的增长, JavaScript 已经成为开发者和工具链的通用语言
WebAssembly 不会改变这一点
WebAssembly 想要替代的是目前 JavaScript 被强行用来占据的地方:
可以用作编译目标的底层的代码表示形式
As more and more languages and platforms begin to target the web,
随着越来越多语言和平台以 Web 为目标, JavaScript 有着更多的压力
浏览器提供商为此尽可能加入缺失的功能
其中一些功能在已经很复杂的 JavaScript 语义当中不能运作地很好
WebAssembly 就是为这个问题提供答案:
它从一开始就被设计为编译目标
它将得到所有主流浏览器提供商的支持
它可以根据需要任意地偏离 JavaScript 原有的语义
WebAssembly 对于 Web 来说是对 JavaScript 很有必要的补充
如果你过去几年跟进了 Web 的发展你就知道 WebAssembly 目标很有难度:
为不能轻易映射到 JavaScript 的语言提供一套统一的编译目标.
不仅仅从技术方面来说目标很艰难, 而且从标准方面来说也是困难的
Web 并不是由单一的提供商控制, 每一个改变都一定是联合的努力
幸运的是, WebAssembly 背后的团队知道这一点.
在 Mozilla, 一群专家开发者尝试通过 ASM.js 的形式提供答案:
用一个套 JavaScript 的子集作为编译目标
另一方面, Google 致力于 Native Client(NaCl) 和 Portable Native Client(PNaCl):
一套基于 LLVM 的 Web 的二进制格式
尽管每个方案某种程度上取得了效果, 但他们没有能的方所有问题提供满意答案
基于这个经验 WebAssembly 才浮现出来: 联合努力来提供跨浏览器的编译目标
WebAssembly 的未来看起来一篇光明
Web 的一个基础特性就是向后兼容性, WebAssembly 也不例外:
对于就浏览器将会有一套 polyfill. 而且, 它的 原型 已经有了
你可以在 这里 和 这里 看到它们已经在使用
当听到"汇编"这个词你也许马上在脑子里听到"可读性差"这句话
幸运的是, WebAssembly 不是这样. 相对于其他底层代码表示形式,
或者大多数的二进制码, WebAssembly 描述的是抽象语法树(AST)
是的, WebAssembly 提供了高级的结构, 比如循环和分支
意味着可以直接写 WebAssembly, 或者反编译二进制文件
从而得到可读性比较好的 opcodes 或者指令
你可能会想"变量名怎么办?" WebAssembly 将支持编译后文件增加调试信息
这里举了例子 WebAssembly 的文本形式看起来怎么样例子使用了 S 表达式(一种轻量级的 AST 表示):
;; Iterative factorial named (func $fac-iter (param $n i64) (result i64) (local $i i64) (local $res i64) (set_local $i (get_local $n)) (set_local $res (i64.const 1)) (label $done (loop (if (i64.eq (get_local $i) (i64.const 0)) (break $done) (block (set_local $res (i64.mul (get_local $i) (get_local $res))) (set_local $i (i64.sub (get_local $i) (i64.const 1))) ) ) ) ) (return (get_local $res)) )
这里 看完整的例子
那么, S 表达式是最终的格式吗? 不是的, 目前没有 WebAssembly 的官方版本还有另一个例子, 完全不用的语法, 你可能会更熟悉
export func main() i32 { storeI32(temp, 0); var i i32 = 0; done: while (i < 10) { i = i + 1; if (i >= 7) { break done; } } return (i + ifelse(0, 1, 2) * 2) * loadI32(temp) + loadI32(scale); }
可以在 这里 看到
WebAssembly 初步的实现目标是等同 ASM.js 的功能.
也就是说, 能用 ASM.js 做的, 等 WebAssembly 推出之后你也能做(做得更好)
第一个版本的可以期待的一个改进是更好的加载时间
WebAssembly 的二进制版本比起 ASM.js 的文本格式可以更快地解析
所以即便是最初的版本, WebAssembly 也能显示出改进
当前版本的 WebAssembly 叫做 最小可行产品][mvp
将来的版本可以期待有这样一些改进:
完整的线程支持
SIMD 类型和 intrinsics
零消耗的异常(栈审查和展开)
协成
动态链接
DOM 集成
集成垃圾回收
尾递归优化
多进程支持
其中一些功能用 JavaScript 甚至纯粹的 ASM.js 都非常难实现
WebAssembly 基于这样一些需求开发的, 作为优秀的语言平台
将支持上边这些(以及更多的)功能
编译目标语言的一个不足是调试常常变得更难
如果你使用过现在编译到 JavaScript 的任何语言,
你大概体会到过调试有多困难, 要靠记忆力把编译结果映射到源码
WebAssembly 的目标是成为其他语言优秀平台, 所以针对方案已经在做了
跟现今的本地编译器很像, WebAssembly 将允许二进制中存在调试信息,
以及 Source Maps, 用来高所浏览器和调试工具怎么样映射生成代码到源码
易于调试是作为 WebAssembly 规范的一部分的
尽管 WebAssembly 还在初期, 你已经能开始得到它将来能提供的好处了
在"真相 2"里我们提到. WebAssembly 来自于实现 ASM.js 和 NaCl 的多年经验
两套实现提供的所有的好处都将存在于 WebAssembly
如果你现在想要其中一些, 那么 ASM.js 就是优秀的一个方案
比如, Emscripten 现在能把你的代码编译到 ASM.js
如果你认为托付给 ASM.js 现在还不合适, 那么记着, WebAssembly 还只是初期
尽管这样, WebAssembly 首先还是将具备 ASM.js 的功能作为第一个目标
所以不要害怕把将来赌在 ASM.js 上
WebAssembly 开发被作为当前的解决方案的一套升级路线,
所以, 虽然可以开始想想未来了, 但并不意味着 ASM.js 不会得到支持
Hack away!
...
过去几年出现了大量的框架, 编译器和其他类型的方案,
要把已有代码编译到 Web, 结果导致了社区当中的不少的失望
一方面, 不符合 JavaScript 语义和意识形态的功能在实施者的论坛里出现,
在 JavaScript 开发中当中激发了严重的问题
另一方面, 想使用已有代码的开发者, 想使用最喜欢的语言和框架的开发者,
发现他们被拦在 Web 外面, 或者面临着严重的调试门槛(以及其他问题)
即便现有方案如 ASM.js 和 PNaCl 做了大量工作减小这些操心,
然而到现在依然没有合适的跨平台的解决方案. WebAssembly 想解决这个问题
恰当的, 跨平台的, 跨语言的编译目标, 支持优秀的平台必要的所有功能
风险很高, 然而回报也非常丰厚. 背后的团队也很清楚这一点
WebAssembly 是开发者们长久以来期待的想法的演进, 它也是将来