Shopify如何在浏览器之外使用WebAssembly?

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"Shopify致力于让大多数商家都需要的功能变得简单易用,并通过接口在Shopify平台上执行查询、扩展和更改,进而为商家提供更多可能。借助这些接口,我们丰富的合作伙伴生态系统可以解决诸多问题。这一生态系统主要借助“App”(一个独立托管的Web服务)来运作。该App通过网络与Shopify进行通信。尽管这种模式很强大,但会带来一系列技术问题。我们的合作伙伴需要打造能够随Shopify规模扩展的Web服务,这让一些本就资源有限的合作伙伴越发捉襟见肘。即便合作伙伴有无限的资源,在与Shopify通信时产生的网络延迟也足以让我们的App在对时效性要求很高的用例中败下阵来。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"我们希望我们的合作伙伴能够专注于利用他们的专长来解决问题,而不用花费时间管理可扩展的Web服务。为实现这一目标,我们保留了不受信任的合作伙伴代码的灵活性,并将其在我们的基础设施上运行。为了确保这些代码的性能、安全性与灵活性,我们选择了WebAssembly这种通用格式。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"WebAssembly"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"什么是WebAssembly?"},{"type":"link","attrs":{"href":"https:\/\/webassembly.org\/","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"WebAssembly.org"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"给出了如下定义:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"”WebAssembly(缩写为Wasm)是一种基于堆栈虚拟机的二进制指令格式。Wasm是为编程语言设计的可移植编译目标,使客户端和服务器应用程序能够在Web上部署。“"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"如需详细了解WebAssembly及其历史,可以浏览由"},{"type":"link","attrs":{"href":"https:\/\/hacks.mozilla.org\/2017\/02\/a-cartoon-intro-to-webassembly\/","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"Mozilla的Lin Clark"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"link","attrs":{"href":"https:\/\/hacks.mozilla.org\/2017\/02\/a-cartoon-intro-to-webassembly\/","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"撰写的这篇图文并茂的"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"link","attrs":{"href":"https:\/\/hacks.mozilla.org\/2017\/02\/a-cartoon-intro-to-webassembly\/","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"文章"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"。本文在此不做详述。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"Wasm通常都是与JavaScript一起在浏览器内运行,但Shopify却另辟蹊径,在浏览器之外运行Wasm,并且不用到JavaScirpt。作为一款高性能语言,Wasm绝非JavaScript的单纯替代品:它面向"},{"type":"link","attrs":{"href":"https:\/\/webassembly.org\/docs\/non-web\/","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"W"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"link","attrs":{"href":"https:\/\/webassembly.org\/docs\/non-web\/","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"eb和非"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"link","attrs":{"href":"https:\/\/webassembly.org\/docs\/non-web\/","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"W"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"link","attrs":{"href":"https:\/\/webassembly.org\/docs\/non-web\/","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"eb的嵌入"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"而设计,解决了广泛存在于浏览器和代码执行引擎中的一个难题,即如何在不受信任的环境中高效执行程序。Wasm满足了我们的三大主要技术需求:安全性、性能和灵活性。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"安全性"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"运行不受信任的代码具有极大的风险。从本质上来讲,这些代码不仅难以预测,并且还很有可能对整个Shopify平台造成损害。尽管市面上并没有百分之百安全可靠的应用,但我们还是要防范安全漏洞,并且在出现问题后采取措施来减轻其影响。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"Wasm将代码执行放到了一个基于堆栈的沙箱环境中,依靠显式导入来与主机进行通信。因此,我们无法在Wasm中"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}},{"type":"strong"}],"text":"写入"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"任何恶意代码,只能使用提供的输入端口操作虚拟环境。在这一点上Wasm与字节码有所不同,字节码在语法中直接引用了它们希望在其中运行的计算机或操作系统。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"Wasm还有很多不同的功能,可让用户免受错误代码的影响,包括受保护地调用堆栈和运行时类型检查。WebAssembly.org上提供了更多"},{"type":"link","attrs":{"href":"https:\/\/webassembly.org\/docs\/security\/","title":null,"type":null},"content":[{"type":"text","text":"关于Wasm安全模型的详细资料"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"性能"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"在电商领域,较快的运行速度才是商家推动业绩增长时必备的利器。如果Shopify提供的功能无法兼顾加载时间和定制价值,那么这种功能压根就没有任何价值可言。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"Wasm本身的设计充分利用了常见的硬件功能,并在各种平台上发挥出最接近原生的性能。它面向追求最高性能、优化浏览器执行的开发者社区。因此,无论是现在还是未来,Wasm和它的周边工具在设计上都会以性能优化为中心。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"灵活性"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"能帮助开发者提高开发效率的代码执行服务才是真正有用的服务。Wasm作为一款字节码格式,与多种编译器相兼容,为代码开发者提供了支持多种编程语言的一流开发体验。这也让我们能够在不改变底层执行模型的情况下,提供多语言支持。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"基于社区"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"Shopyify在发展目标和设计方面基本保持一致,这为我们选择Wasm提供了技术上的理由,但事实并不仅限于此:我们对Wasm的选择不仅关乎于技术,更关乎于人。如果Wasm生态系统无人问津,或者它仅在生死线上垂死挣扎,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}},{"type":"strong"}],"text":"那么我们不会选择它"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"。WebAssembly的社区是个充满活力的社区,不断创新,它的潜力是无穷的。自从加入这个充满热情的社区,Shopify就获益匪浅。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"同样,我们也在为社区贡献出我们的力量。通过收集用户反馈,探讨功能缺陷,以及为我们使用的开源工具提交代码贡献。我们认为,这为我们与WebAssembly社区之间建立良好的互惠合作关系打下了坚实基础,我们也期望着在未来能够继续为这个鲜活的社区献出我们的力量。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"代码执行服务的架构"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"在简单介绍过WebAssembly以及我们选择它的原因后,下一步就来深入探讨我们的运行方案。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"我们使用的是最初由Fastly开发的开源工具"},{"type":"link","attrs":{"href":"https:\/\/www.fastly.com\/blog\/announcing-lucet-fastly-native-webassembly-compiler-runtime","title":null,"type":null},"content":[{"type":"text","text":"Lucet"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"。Fastly这家公司为大批量寿命不长且不受信任的模块提供了一个可编程的边缘云平台,让它们可以在尽可能接近发起请求的地方执行请求。这与我们的合作方提供的代码所面临的问题相同,因此,我们自然而然就选择了Lucet。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Lucet"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"Lucet是Wasm的运行时和编译器。Wasm中的模块确保了系统的安全性,由于我们无法在Wasm中写入恶意代码,因此Lucet利用Wasm模块的验证进行安全检查。在验证之后,模块会被编译为一个可执行的文件,其性能可以达到原生状态。另外,Wasm还支持提前编译,可避免执行运行时编译带来的延迟。Lucet容器在启动时无需执行任何操作,这让它拥有了令人惊叹的35μs启动时间。如果您对Lucet及其工作原理感兴趣,可以去看看"},{"type":"text","text":"Fastly的CTO Tyler McMullan的"},{"type":"link","attrs":{"href":"https:\/\/www.youtube.com\/watch?v=QdWaQOgvd-g","title":null,"type":null},"content":[{"type":"text","text":"演讲视频"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/38\/3835624acc4cd97ba1246e008da311a4.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}},{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"Shopify中Wasm引擎的工作原理流程图"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"我们将Lucet包装在一个管理I\/O和模块存储的Rust Web服务里,并将其称作是Wasm引擎。在运行时,Shopify通过Web请求调用Wasm引擎以处理部分功能。引擎之后再调用站点的上下文中应用输出,这里的上下文可能会涉及到创建折扣、执行约束,或者是任何商家想要在平台中私人定制的同步服务。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"运行性能"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"下图中是我们在最近一次的性能测试中提取到的一些指标。我们选择了一个很小的功能及逆行测试:让模块对用户购物车中添加的物品数量进行限制。在测试期间,每分钟执行十万个模块,持续时间约5分钟。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/dd\/dd50ec6c61f6b611373d41c2ffb8730b.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}},{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"模块执行所需时间"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"该图表展示了执行一个模块所需时间的详细情况,其中包括容器的I\/O和模块的执行。y轴代表时间(单位:ms),x轴代表测试运行的具体时间。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"图中的浅紫色图例代表Lucet中执行模块需要的时间,其宽度大约在100μs左右徘徊。其余图标则是I\/O的处理和引擎的具体情况,可以看出执行的全部时间大约在4ms左右。所有的时间显示都是第99位百分比(99p)。为了能更好地理解图中时间的含义,下面让我们将用Shopify中"},{"type":"link","attrs":{"href":"https:\/\/shopify.engineering\/how-shopify-reduced-storefront-response-times-rewrite","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"性能卓越的在线商店渲染服务"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"link","attrs":{"href":"https:\/\/shopify.engineering\/how-shopify-reduced-storefront-response-times-rewrite","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":":"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"link","attrs":{"href":"https:\/\/shopify.engineering\/how-shopify-reduced-storefront-response-times-rewrite","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"Storefront Renderer"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"的测试请求时间做比较。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/7d\/7dcc2daf10ac7d2d6b1f2c1d4e784599.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}},{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"Storefront Renderer响应时间"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"这张图表中展示了Storefront Renderer在一段时间内的请求时间。y轴代表请求时间(单位:秒),x轴代表返回数值时的具体时间。浅蓝色线条代表在700毫秒左右的第99百分比。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"如果将模块处理时间大致估算在5毫秒内,那么可以说Lucet执行时间带来的性能影响几乎可以忽略不计。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"生成WebAssembly"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"为了让我们性能卓越的执行引擎发挥作用,我们还需要授权开发者创建兼容的Wasm模块。Wasm的作用并不是让用户亲自编写("},{"type":"link","attrs":{"href":"https:\/\/blog.scottlogic.com\/2018\/04\/26\/webassembly-by-hand.html","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"想写"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"link","attrs":{"href":"https:\/\/blog.scottlogic.com\/2018\/04\/26\/webassembly-by-hand.html","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"当然是"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"link","attrs":{"href":"https:\/\/blog.scottlogic.com\/2018\/04\/26\/webassembly-by-hand.html","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"可以写的"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":")代码,而是作为一个编译目标存在。这就会让我们思考以下问题:我们支持哪些编程语言,具体又要支持到什么程度。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"理论上来说,任何有Wasm支持的开发语言都是可以的。但是,我们更希望开发者可以将精力集中在为商家解决问题上,而不是研究要如何符合我们的API。这也是我们选择单一语言Ruby支持,并为开发者提供快速启动工具的原因。然而,由于Ruby动态语言的特性,我们并不能将其直接编译为Wasm,而涉及编译解释器的解决方案会有严苛的性能惩罚。正因如此,我们最终决定采用静态编译的语言,并将动态语言编译的可能性留待未来。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"通过我们的调研发现,Shopify生态系统中的开发者大多能对JavaScript熟练应用。可惜的是,由于JavaScript与Ruby一样是动态语言,只得被排除在外。最终,我们选择了一种语法类似于TypeScript的开发语言:"},{"type":"link","attrs":{"href":"https:\/\/www.assemblyscript.org\/","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"AssemblyScript"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"使用AssemblyScript"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"虽然WebAssembly支持大量开发语言,但其中有两大类编译器是我们无法使用的:"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"生成环境或开发语言特定产物的编译器,即节点或浏览器。(例如"},{"type":"link","attrs":{"href":"https:\/\/github.com\/tweag\/asterius","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"Asterius"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"underline"},{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"、"},{"type":"link","attrs":{"href":"https:\/\/dotnet.microsoft.com\/apps\/aspnet\/web-apps\/blazor","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"Blazor"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":")"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"只适用于特定运行时的编译器。这些编译器生成的模块依赖于特定语言的特定导入,通常是为了支持某些特定语言的标准库,让他们能够在系统调用或运行时功能可用而存在的。因为我们并不想被锁死在某一特定语言上,所以这类编译器就不在我们的考虑范围内了。(例如"},{"type":"link","attrs":{"href":"https:\/\/github.com\/lumen\/lumen","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"Lumen"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":")"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"这些功能强大的编译器在其他情况下或许能够发挥奇效,但可惜无法为我们所用。我们需要能够生成WebAssembly的工具,而不是由WebAssembly"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}},{"type":"strong"}],"text":"支持"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"的工具。AssemblyScript便是被我们选中的工具。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"与WebAssembly中的其他工具一样,AssemblyScript还在开发过程中。它缺乏一些诸如闭包支持等关键功能,在边缘情况下仍会报错。这时候就显现出了社区的重要性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"开发语言AssemblyScript和它的周边工具拥有一个用户活跃的爱好者和维护者社区,自从2019年Shopify首次使用AssemblyScript以来,他们就一直在支持着我们。而我们也通过"},{"type":"link","attrs":{"href":"https:\/\/opencollective.com\/shopify","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"OpenCollective"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"长期贡献代码以支持社区。我们编写完成了一个"},{"type":"link","attrs":{"href":"https:\/\/github.com\/saulecabrera\/asls","title":null,"type":null},"content":[{"type":"text","text":"语言服务器"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":",在实现闭包方面也取得里一些进展,也为编译器和周边工具提供了错误修复。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"我们还将AssemblyScript融入了我们早期的工具之中。在"},{"type":"link","attrs":{"href":"https:\/\/github.com\/Shopify\/shopify-app-cli","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"Shopify CLI"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"中,我们通过集成AssemblyScript,允许开发者通过命令行创建、测试和部署模块。为了提高开发效率,我们提供了可以处理Shopify定义对象(例如“Money”)底层实现的SDK。除了这些工具,我们还搭建了一个允许合作伙伴监控模块的系统,方便他们在模块出现故障时收到警报。我们的最终目标是让合作伙伴们能够在不失去代码在原生平台上灵活性和可观察性的前提下,将他们的代码迁移到我们的平台之上。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"新功能,新机遇"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"通过连接商家和合作伙伴,Shopify做到了商家与企业的对接,解决了双方各自面对的问题。如果你对我们的代码执行服务感兴趣,觉得这些对您或者您的App很有用,欢迎在推特上@ShopifyEng。如需了解更多关于Shopify及我们App的信息,请访问我们的"},{"type":"link","attrs":{"href":"https:\/\/developers.shopify.com\/app-development?shpxid=8fd4f017-BFCC-44C0-D87F-C5B766F567F9","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"开发者页面"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}},{"type":"strong"}],"text":"原文链接:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/shopify.engineering\/shopify-webassembly","title":null,"type":null},"content":[{"type":"text","text":"https:\/\/shopify.engineering\/shopify-"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"link","attrs":{"href":"https:\/\/shopify.engineering\/shopify-webassembly","title":null,"type":null},"content":[{"type":"text","text":"W"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"link","attrs":{"href":"https:\/\/shopify.engineering\/shopify-webassembly","title":null,"type":null},"content":[{"type":"text","text":"ebassembly"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章