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"}}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章