Loading…
Bringing Javascript to WebAssembly for Shopify Functions
2023-10-18
- Source
- Shopify
- Published
- Added to Yomu
Summary
Shopify is introducing a Local Developer Preview that lets developers run JavaScript Shopify Functions locally, alongside Rust, while production deployment remains unavailable. Shopify Functions execute as WASI modules that read JSON from stdin and write JSON to stdout, with a 256KB size limit and a five-millisecond runtime limit; the post notes that the timing constraint varies by machine load. Javy addresses JavaScript’s WebAssembly runtime challenge by bundling the QuickJS interpreter into a Wasm binary, using Rust wrappers and Wizer to snapshot compiled QuickJS bytecode. Initial tests found Javy-created modules about three times slower than equivalent Rust modules, but both are likely to stay under five milliseconds for realistic use cases; Shopify is also pursuing SpiderMonkey in Wasm and researching JIT support for future performance.
Context
Shopify developers predominantly use JavaScript, and many were hesitant to try Shopify Functions when Rust was the recommended language. The functions also operate under tight constraints intended to support scalable execution, including a 256KB module limit, a five-millisecond runtime limit, and JSON input and output requirements.
Approach / What changed
Shopify created Javy, a general-purpose JavaScript-to-WebAssembly toolchain that embeds the QuickJS interpreter in a WASI module. Rust wrappers integrate QuickJS, while a two-stage build and Wizer snapshot JavaScript into QuickJS bytecode within the resulting Wasm module. The local preview is accessed through the Shopify CLI and can be built into dist/function.wasm, with SpiderMonkey and possible WebAssembly JIT support planned for future performance improvements.
Takeaways
- Shopify Function modules must be no larger than 256KB, must complete within five milliseconds, and must exchange JSON through stdin and stdout.
- Javy uses QuickJS rather than a JIT-based engine because WebAssembly cannot currently generate and execute new code inside a module.
- Initial testing found Javy modules about three times slower than Rust modules, although both are expected to fit the five-millisecond limit in realistic use cases.