特别说明
这是一个由 simviso 团队对 JSConf.Asia 中关于 WebAssembly 相关话题进行翻译的文档,内容并非直译,其中有一些是译者自身的思考。分享者是 Kas Perch,Cloudflare 的一名开发人员。
现在,让我们一起来了解下什么是 WebAssembly。
视频翻译版权归 simviso 所有
本次参与翻译人员
一、前言
大家好,太棒了。就像他们所说,如果我们搞定了 WebAssembly 技术,那么就搞定了 JS 的未来和 Web 多语言开发。
正如介绍所言,我叫 Kas Perch,现在是 Cloudflare 公司的一名 Avocado 开发人员。同时,我也很痴迷于机器人编程,并且写过相关书籍。
我已经写了两本使用 JS 给机器人编程的书。我周末也会在 twitch 上直播一些硬件和软件相关的东西。
我养了两只猫,它们是我的最爱。左边的猫叫 Ace,右边的叫 Aria。它们现在对我很生气,因为我已经离开它们三个星期了。
我可能再过一个星期才回去,它们是真的很生我的气。
言归正传,你们来到这里就是为了听一些关于 WebAssembly 的一些东西
二、什么是 WebAssembly
这项技术已经有五年了,我们还在维护中,我们冷静下来思考一下,为什么直到现在还没有人指出该如何使用它。因为人们很难做到该如何更容易的去理解它(因为它很抽象),这也是为什么我们要来谈下它到底是什么。
首先,我想说,它不是一个编程语言(注:WebAssembly 是驱动编程语言的存在,此处就相当于一个猎头,针对后面这句话),就像你曾经去领英上面招聘员工一样,你说你需要一个有十年开发经验的 Node.js 程序员。
这个就像是在说,我是一个 WebAssembly 程序员,就好像如果你不会 WebAssembly 编程,你就不会写 WebAssembly 程序(就好比如果你不会 Nodejs,你就不会使用 Nodejs 编程)。
其次,WebAssembly 不会取代 JS ,同时它可以让 JS 驾驭任何事。
JS 并不会没落,更不会被 WebAssembly 打败,因为它并不是为了打败 JS 而设计的。
WebAssembly 恰恰是我们无法去忽视的东西,因为它可以让我们走得更远
我希望在接下来二十几分钟你们能被我征服,因为 WebAssembly 是未来的发展趋势。
不好意思,按错了。
那么 WebAssembly 到底是什么呢?
它为其他语言提供编译服务,你可以将其他语言编译成 WebAssembly,它是一种规范(类似于 jvm 支持的 class 字节码)和要编译成的目标文件类型。
这对于 JS 来说是一种能力的增强。WebAssembly 根本就不是想要取代 JS ,而是仍然让 JS 做它所擅长的领域,同时也能让 JS 也能做它所不擅长的领域,这就是它要做的事情。
但更重要的是,WebAssembly 表面上很神奇,但却不仅仅只是表面上神奇,我会在后面解释这点。
WebAssembly 的目标就是将你用其他语言写的代码编译成 wasm 类型文件。
WebAssembly 已经很好的支持了 Rust 语言,C/C++,GO 和 C# 已经可以用 WebAssembly 编译。
还有很多语言没有提到,当然我能想到的主要就这四个,尤其是 Rust, WebAssembly 对它进行了相当多的优化,你有机会可以尝试一下,这绝对是一个非常酷的编程体验。
那么这里,你可能会问:为什么要用其他语言来写 Web 程序?你为什么要这么做?为什么你会在这里放上 Laurie Voss(npm 的作者) 的演讲照片,然后你使用其他语言来讲这些东西?
主要有两个理由:A,我想要和 Laurie Voss 进行合照。B,让大家一起拥抱 WebAssembly。
三、下一个 Ajax
对于浏览器来说它就像是下一个 Ajax(就好比是下一个乔布斯)。
在这周末,我已经看到了很多有这样(惊讶)表情了。
OK,就像下一个乔布斯(这里是 Ajax),听起来很酷。
但是我的意思是说 Ajax 真的高度可信并且使客户端层面应用成为可能,所以说,Ajax 是一个变革,而 WebAssembly 将是下一步的一个变革。
这是我今天早上找到的一张超可爱的宝可梦 GIF,我就想着要把它贴上来。
为了跟贴图保持一致我特意选用了“进化”这个词,不知道你们注没注意 GIF 周边我还写了字的哈。
这时候你可能想着说,行吧,可能这就是下一个 Ajax,但还是抱着几分迟疑态度。
这幅画是我早上在 OneNote 上画的。
我把它称为 “ancient.png.”
让我们回过来看这张图,这上面有 HTML,CSS 和 JS。
比如当你打开社交网页的时候js就会播放烦人的音乐,服务器会返回所有这些东西,所有的东西都在这里。
请将你的视线随着我手指移动,当你点击一个链接的时候,它会返回一个页面,你一直点击它就一直会给我们返回一个页面。
每当你想要从服务器获取新信息的时候,你就需要手动对浏览器进行刷新操作。
我将这张图称之为 then.png,Ajax 不是一个 button 但胜似 button。
Ajax 请求页面,然后获取页面内容,我们通过发送 Ajax 请求,来避免刷新页面的操作。
我们通过 Ajax 得到返回的结果,Ajax 结果可能会是另外一个页面的请求。
基于这个,我们得到了一系列的单页应用程序。
当我们的服务器提供了Restful 风格的 API 的时候,也提供临时的 HTML CSS 和 JS 文件。
这才是我要说的,请看我用高亮颜色所标记出的 WebAssembly 的内容,这里突出了它的工作原理。
可以看到页面请求、返回的页面结果,在这个过程中 WebAssembly 只是做一些计算而已。
我们依然来看两个图中左侧的 Browser,然后使用 service worker 作为你的第三方模块。同样是在这个Browser中,你可以使用一些 Ajax 请求,同时服务器就类似于图上的 LOL OK。我可能甚至都不是一个真正的服务器,我只是 serverless 服务器上的一个函数而已。
然后返回你的结果。整个过程简直不可思议!
OK,相信你现在应该有点感觉了。
四、对 JS 进行增强
能够在浏览器中计算内容,不一定非要用 JS 来实现。
这就是一件大事!相当重要!
那为什么这很重要?为什么我们要这么关注?
我们之所以这么关心是因为我们对 JS 进行增强。
我知道,这个话题你也许听到过很多次,甚至都已经厌倦了。但是这也是事实,JS 在某些方面的确不擅长。
我们并不需要为了使用 WebAssembly 而重写整个项目代码,谁也不想重构整个代码库,就像五年前那些包含了单元测试的代码,我想没人愿意来干这个事情(想重构举起你们的手,但是没有)。
挺好
更少的请求调用意味着更少的延迟,也就意味着我们可以为用户提供更快的 Web 应用。
高性能一直都是很重要的。这样的话,我们就无需对服务器进行成千上百万次的请求。
所以,我们来谈谈该如何对 JS 进行增强。
我相信在你的工作过程中已经看到过很多次这种表达式(0.1 + 0.2 === 0.3 // false)了吧,其实0.1 + 0.2 = 0.30000000000000004(精度运算),所以 0.1 + 0.2 === 0.3 是 false
所以如果你正在做的事情对数字精读有很高的要求,比如:金融应用、股票交易、货币兑换。那么很显然,这些并不是 JS 的强项。
你需要对那些运行着不同语言的服务器发送一个 Ajax 请求,服务器会返回给你精确的结果,然后你对返回的结果进行了错误的转换(通过 JS 对返回的 JSON包含的数字类型的字符串进行转换,出现精读丢失)。
所以通过 WebAssembly,你就可以在浏览器中使用正确的工具来完成这项工作,比如:Rust,C,或者其他浮点数超过32位的语言。
其它 JS 不太强的地方还有,JS 的类型强制转换会有一些负面效应,比如:" " == 0 为 true。我真的很难去理解它,我可以说他们输入了一个非零的数字。
得到和预想中不一样的结果,这个结果对我来讲完全是出乎意料的,比如你用 1 和通过选择器(document.getElementById)获取的 input 的值相加,结果只是连接字符串。但是你使用 Number函数处理 input 元素的值,那就会进行两个数字相加,即使后者不是一个真正的数字,可能只是一个 NaN,然后 1+ 9可能也是 NaN。
这下知道我的意思了吧,类型强制转换在这里会很棘手。
说到类型,typeof 关键字是一个迷。就像图中最后一条一样,让人烦躁了很多年(typeof [] === ‘array’ // false)
如果你之前看过我的演讲,你就会知道使用了 WebAssembly 也就意味着使用了正确的工具来完成对应的工作。工欲善其事必先利其器。
WebAssembly 使用正确的工具来完成 Web 上的工作。
我们不需要再通过 JS 来做它不擅长的事情。
这对 Web 和浏览器应用程序来说都是一件大事。
但是这将会干掉 JS。
噢, 我们将会使用 WebAssembly 去写所有的应用程序,WebAssembly 将会…,不,冷静,冷静。
开个玩笑,它不会干掉 JS。
它让 JS 做它擅长的事情,从而使它变得更好。在 DOM 操作上,React 和其他框架会快得离谱,JS 引擎也使 DOM 操作速度更加快。
我不认为 WebAssembly 会很快打败 JS 和 DOM 操作。也许在遥远的将来,它可以做到,但是近期看来并不会实现。
并且 JS 也很擅长于操作 CSS 样式,WebAssembly 也不会取代 JS 去操作 CSS。
所以,WebAssembly 用于增强 JS,同时你也可以在此基础上使用 JS,这并不矛盾。
并且 WebAssembly 解决了 JS 所不擅长的,这也减轻了 JS 的负担。
就好像我和我的对象一样。他是很讨厌洗衣服的,真的,特别讨厌。而我又特别讨厌做菜,所以他做菜我洗衣服,并且这样搭配非常完美。
但是现在他还是必须洗自己的衣服,因为我要出差三周,而他只有两周的衣服穿,所以不得不洗。
就像 Ajax 做的那样,WebAssembly 通过营造更好的浏览器体验来使互联网变得更好。
当你想到这些影响时,这更好的浏览器体验简直令人激动。就像 Jeff Goldblum(美国演员)令人激动那样。
五、举个例子
让我们通过这个 Demo 来进一步表达我的意思。
这个 Demo 使用了 wasm-imagemagick 技术,如果你之前没有用过 imagemagick 的话我可以解释一下:imagemagick 是一个命令行工具,专用于创建和操纵图片。
它能够创建GIF动画,它能够创建图片的单元格,它能够创建分形图。它是一个非常强大的库以至于我不想用任何其他语言去重写它,更不用说 JS。
我们将要以十倍快于 JS 的速度来操纵这些图片,所以从某种意义上说 JS 本身并不能做到。
它真正强大的地方在于你不用重写任何代码就可以通过该工具来完成我们的工作。
让我们来看看。希望这行得通。
它之前都是好好的所以这次可能就不行了,你知道我意思吧。
好了我摄像头打开了。我们来选择一张照片,我要点下面(做鬼脸),照片照出来总是显得我很蠢,所以我放弃挣扎了。
OK,这些按钮的意思是……我把它调大一点你们就看得清了我的舌头和这些按钮了。
我们点右旋,然后在下面你就可以看到右旋的图片了。这真的真的是很快的了,再左旋一下,你用 CSS 也能快速做到,这好像没什么了不起。我们来调个灰度,boom, 灰度,没有闪屏。我们来加点对比度。去掉对比度呢?去掉对比度了。JS 能这么快吗?不可能!
对,这就是我的 Demo,我会在推特上发一下这个 Github 仓库,这是完全开源的,你想的话可以尝试一下。
对,这是我的 Demo。
哈谢谢你们
六、关于 Nodejs
但是 Nodejs 呢?等等……关于 Nodejs?
这是浏览器的工作,对,这完全是浏览器中的技术,我刚刚说的也完全是跟浏览器相关的。
但是,为什么我会提到 Nodejs 呢?
我提及它(Nodejs)的原因是它是模块本地化的,有谁在跑 npm install 的时候看到过 C 编译出错?
大部分人的手都应该举起来了,因为这实在是太常见了,模块本地化实在是 Node 中的一个大坑。
这东西真的非常愚蠢,甚至让你想喊出 Bryan Cranston(绝命毒师男主)嘴里喊的。你可能能从他的唇语里读出来,他喊的是 BLAH,他喊得并不是…额你知道的
为什么这些模块如此之坑?原因是它们必须在下载时重新编译,而且必须为每一个体系结构重新编译它们。
就拿树莓派平台来说,因为在这个平台上根本不能正常的工作,就会有人在 Github 上面去提issue ,同时也就意味着你会花很长时间在 Github 上去讨论这个问题。
他们要么会为你的平台编译一个版本,要不就直接不支持这个平台。
的确这也是很棘手的,Github 上面的讨论的确让人感到糟糕。但是我很遗憾的告诉你,这个并不支持 Windows 系统。
首先声明,我很感激hecc(高等教育协调理事会)在 node-gyp 方面所做的研究,他们完成了这是个似乎不可能完成的任务。因此我很尊重他们。
但是 WebAssembly 只能在 Node8.0 以上版本正常工作。记住这个8.0版本,为什么他可以在 Node8.0 以上的版本运行呢?
因为这个版本的 WebAssembly 模块已经预编译了,不需要构建。所以这对于任何平台都是十分便捷,都可以通过 Node 来运行。所以对于整个架构,都不会再有下载重编译这个步骤了。
的确是这样,我已经试过了,你也可以尝试一下,这真的太棒了。
引用 Laurie Voss 今天早上说的一句话
每个人都不看好 node-gyp,但是 WebAssembly 恰恰让我们做到了。
这是 Nodejs 的里程碑。在不久的将来,当 Node8 不在维护的时候,Node8 以下的版本将不再兼容。
这并不意味着人们不能使用它,比如 Android3.0 版本。
其它
OK,WebAssembly 正在往 serverless 上进击。例如,我在 CloudFlare 工作,我们有运行着 V8 引擎的云平台,所以你可以在 serverless 上运行 WebAssembly,这很酷!
我们现在为现场的听众提供了一个免费的 serverless 平台。
我的意思是,假设你们中的某些人正在观看这段视频或者直播,但是你们没有这个平台的会员,然后还想白嫖。不要误会我的意思哈,我只是也不喜欢付款而已。
如果你扫描这个二维码,你可以保留一个 workers 的子域,而不是 dev 环境,它包含了 30 个 worker ,每天能处理 10 万个请求,在每秒内,比我不使用 JS 做运算要稍微多一点。
这个我之后会再展示,它在我们的展位上也有放。但我会等你们都扫完,我再切到下一个 PPT。放二维码显然不是因为我不想让你们看见我。
我想大家基本都扫完了。
这次谈话的重点是试着拥抱 WebAssembly ,我个人特别喜欢 Rust。
我学到更多关于 Rust 的知识就像我学到新东西一样。就好像这不是在 13 天内创造出来的。
我没有瞧不起 JS。它是有史以来最好的语言之一,但它是在13天内完成的,而 Rust 绝对不是在 13 天内完成的。
它绝对是经过深思熟虑的。
WebAssembly 是 JS 所有形式的未来,尽管我希望能向你展示它将创造更好的浏览器体验。
它将弃用 node-gyp。
从现在起的五年里实际上它并没有这样做,请不要引用我的话。
但它可能会弃用 node-gyp。你可以引用我的话。
最后一个问题是,如果你现在是招聘经理,我想让你做一些非常重要的事,那就是雇佣一个和你不同的人。
他们可能与你有所不同,他们可能会相信你的不同之处,他们可能会有所不同,他们的性别认同可能与你雇佣他们的性别不同。
在你告诉我这很难之前,我会让你去找 LaBeouf 先生谈这件事。
不难,尽管去做!
有人会以某种方式雇用与你不同的人。
不管怎么样,感谢大家的聆听 ~