Build a Shopify Function using AssemblyScript
Shopify Functions allow you to inject custom code that modifies the backend behavior powering Shopify. Right now, that just means you have a way to apply discounts without worrying about Shopify Scripts.
This quick write up and the linked example should make it easier for JavaScript/TypeScript developers to dive into Shopify Functions without having to learn Rust.
Update (13/04/2023): Shopify has released JavaScript support for Functions since this post was originally written. The current JavaScript implementation has some limitations compared to Rust or AssemblyScript, most notably performance, with JavaScript Functions running around 3X slower than Rust. AssemblyScript performance is closer to Rust, as the JS runtime does not need to be compiled into WASM. That said, for simple Functions, Shopify's JavaScript solution should work well. If you are still interested in AssemblyScript or need better performance for your Function compared to Shopify's JS solution, keep on reading! Otherwise, I recommend you checkout one of Shopify's JavaScript Functions tutorials.
TL;DR: check out our AssemblyScript Function
You can take a look at the Function example written in AssemblyScript in Gadget’s examples Github repo. If you want to try it out yourself, copy the folder over to your local environment and use it as a new Shopify CLI app extension. Instructions for building and running are in the README.
WTF (WASM, the Function)
“Like a typical function you define an input, write the logic of your function, and then write out the output.” - Shopify Functions docs
“Well, that sounds easy enough.” - me
But wait a tick, Functions need to be deployed as .wasm files. I need to write my code in a language that can be compiled to WebAssembly.
I have zero previous experience working on projects that compile down to WebAssembly. Shopify’s Functions tutorial is written in Rust, a notoriously difficult language to learn. I went through the tutorial, was able to get the demo discount running (Note: you need to create a new development store and enable checkout extensibility, otherwise your Function will not work!), and was getting ready to dive into the Rust documentation so I could write a Function to handle product bundles, when a coworker suggested I check out AssemblyScript instead.
Why AssemblyScript?
AssemblyScript is written in a syntax that resembles TypeScript. It was easy to set up using npm and much easier to read for someone with a background in frontend development, like myself. And because of that, the learning curve was much smoother compared to a language like Rust. It only took a day or two to learn the basics of AssemblyScript and recreate the Function in Shopify’s discounts tutorial.
The relative speed and ease of use seem to be big advantages when I just want to write small Functions. I don’t need to go deep into AssemblyScript to do some basic computing – it’s just a couple utilities and and adapters without manual memory management, a whole new standard library to learn, or any wildly complicated build chains. When doing simple discount manipulation, like in Shopify’s tutorial, this is enough.
Another advantage, you can use your favorite JS test runner along with Shopify’s function-runner to test your compiled .wasm file. I used Jest in order to add some simple unit tests for my Function.
Why Rust?
There are some downsides to using AssemblyScript, namely the smaller community and reduced feature set compared to Rust. Rust’s community is active and growing, and it will most likely be easier to find solutions to problems on StackOverflow or Github compared to AssemblyScript.
You may need to test and debug imported AssemblyScript npm packages because they aren’t as mature as their Rust counterparts. I ran into some issues with the serializer package I use in the tutorial, for example. At times, it might feel like you’re one of the 12 people currently working in AssemblyScript. This can be exciting, but also frustrating. Hopefully Gadget’s provided utilities help you to avoid issues I ran into when building and deploying this Function.
Other strengths of Rust like performance and safety are big pros for large scale software development, but for Shopify’s 100-line-or-so-functions, I didn’t feel like they really mattered that much.
There are also curated lists of languages that compile down to Wasm available on Github, so there is a ton of opportunity to choose your own adventure.
What’s next?
Once again, you can check out Gadget’s AssemblyScript sample on Github. Feel free to try it out or modify it to suit your needs! Instructions are in the README file.
Join us on Discord if you want to help us build and release an AssemblyScript package for working with the Shopify Functions API!