You can write your functions in Rust. This guide describes the [`shopify_function`](https://crates.io/crates/shopify_function) Rust crate that Shopify provides to help developers build with Shopify Functions.
## Requirements
You need to have `graphql_client` installed as a dependency in your project:
## How it works
The `shopify_function` Rust crate bundles `graphql_client`-based type generation, reduces boilerplate code, and makes it easier to test various function inputs. It includes the following components:
| Component | Description |
| --- | --- |
| `shopify_function_target` | An attribute macro that transforms the following function to:- Generate structs and output types for the Function API target from the specified [input query](/docs/apps/build/functions/input-output#input) and [GraphQL schema](/docs/apps/build/functions/input-output#graphql-schema).
- Export a WebAssembly function with the specified name, which must match the target export in the [function extension configuration](/docs/api/functions/configuration#properties).
- Automatically handle input parsing from `STDIN` and output serialization to `STDOUT`.
|
| `run_function_with_input` | A utility for unit testing that enables you to add new tests based on a given JSON input string. |
## Viewing the generated types
To preview the types generated by the `shopify_function` Rust crate, use the [`cargo doc`](https://doc.rust-lang.org/cargo/commands/cargo-doc.html) command.
You can also use the [cargo-expand](https://github.com/dtolnay/cargo-expand) crate to view the generated source:
## Development tools
To make development easier, install the [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) VSCode extension for:
- Code completion
- Go to definition
- Real-time error checking
- Type information on hover
> Note:
> The generated `.output.graphql` files are used for output type generation purposes. You can add these files to your `.gitignore` file.
## Example implementations
Explore example implementations using the `shopify_function` Rust crate.
## Binary size tips
Shopify Functions compiled Wasm file must be under 256 kB. Here are a few tips to keep binary size small when using Rust:
- Update the [`shopify_function`](https://crates.io/crates/shopify_function) crate to the latest version.
- For regular expressions, use the [regex_lite](https://docs.rs/regex-lite/latest/regex_lite/) crate.
- Follow tips and documentation in the [johnthagen/min-sized-rust](https://github.com/johnthagen/min-sized-rust)
GitHub repository.
- Use [`wasm-snip`](https://github.com/rustwasm/wasm-snip) to remove the
panicking code, then `wasm-opt` to strip debug information. For example:
```
# Change this line:
export WASM_PATH=target/wasm32-wasi/release/your-function-name.wasm
RUSTFLAGS="-C strip=none" cargo build --target=wasm32-wasip1 --release \
&& wasm-snip --snip-rust-panicking-code $WASM_PATH \
| wasm-opt -O3 --enable-bulk-memory --strip-debug -o function.no-panic.wasm -
```
- Use `to_ascii_uppercase` and `to_ascii_lowercase` when possible to avoid
pulling in Unicode tables, unless needed.
- Only query for data you need.
Code generation happens for all types and fields included in the
input queries (for example, `run.graphql`). Review and remove any unused
parts of the queries.
- Keep JSON metafields that require deserialization as small as possible.
Code generated for deserialization increases the binary size. The
smaller the metafield is, the less code needs to be generated.
- Bring your own types and deserializers.
Instead of using the generated structs from the `shopify_function_macro` crate,
write the appropriate struct definitions and derive the deserializers
using [`mini_serde`](https://github.com/dtolnay/miniserde).
The structs from `shopify_function_macro` can be used as a starting point, see
them with [`cargo expand`](https://github.com/dtolnay/cargo-expand).
Alternative serializers are generally less efficient than serde,
make sure to benchmark the instruction count when going down this path.
## Updating to Rust 1.84 and higher
Previously, we encouraged the use of `cargo-wasi` as a way to build and optimize your Rust functions. However, as of Rust version 1.84, the WebAssembly build target used by `cargo-wasi` will be removed.
To migrate an existing Rust function to Rust version 1.84 or higher, complete the following steps:
1. [Update to the latest](/docs/api/shopify-cli#installation) Shopify CLI version.
1. Remove the deprecated `wasm32-wasi` build target using [`rustup target`](https://rust-lang.github.io/rustup/cross-compilation.html):
1. Update your Rust version using [`rustup update`](https://rust-lang.github.io/rustup/basics.html):
1. Install the new `wasm32-wasip1` build target using [`rustup target`](https://rust-lang.github.io/rustup/cross-compilation.html):
1. Update your build `command` and `path` in the `[extensions.build]` section of your [`shopify.extension.toml`](/docs/apps/build/app-extensions/configure-app-extensions#shopify-functions-extensions). Replace `RUST-PACKAGE-NAME` with the `name` from your `Cargo.toml`:
These changes are compatible with Rust 1.78 and higher.
> Note:
> In addition to building your Rust function for WebAssembly, the `cargo-wasi` crate also optimized the size of your binary using the [Binaryen](https://github.com/WebAssembly/binaryen) toolchain. Shopify CLI will now optimize your module by default. You can configure this behavior via the `wasm_opt` [configuration property](/docs/apps/build/app-extensions/configure-app-extensions#shopify-functions-extensions).
## Migrating from JavaScript
Migrating your JavaScript Shopify Function to Rust can significantly improve performance and help you stay within platform fuel limits. Rust compiles directly to WebAssembly, resulting in more efficient execution compared to JavaScript.
### JavaScript migration steps
1. Generate a new function using Shopify CLI:
2. When prompted:
- Choose the same function type as your existing JavaScript function
- Name it the same as your current function but append `-rs` (e.g., if your current function is `product-discount`, name it `product-discount-rs`)
- Select `Rust` as the language
3. Copy your existing GraphQL query, making these adjustments to support the Rust code generation:
- Copy your `run.graphql` from your JavaScript function to the new Rust function's `src` directory
- Rename the query from `RunInput` to `Input`
- Add `__typename` to any fragments on interfaces or unions:
4. Port your JavaScript logic to the generated `src/run.rs` file
### Reusing extension handles
By reusing the extension handle from your JavaScript function, you can seamlessly replace the existing function on the server. This means all existing instances of your function will automatically use the new Rust implementation without any changes required on the merchant's side.
Migration steps:
1. Copy the existing handle from your JavaScript function's `shopify.extension.toml`:
2. Update your new Rust function's configuration with the copied handle:
3. Disable the JavaScript function by renaming its configuration file:
> Warning:
> If you deploy both functions, they will both appear in the merchant admin, which may cause confusion. Always ensure you've disabled the JavaScript function before deploying the Rust version.
### Validating the migration
Before deploying to production:
1. Test the function locally:
2. Deploy to a development store and verify the function works as expected
3. Confirm only one function appears in the merchant admin
4. If everything works correctly, you can safely delete the JavaScript function directory
## Next steps
- Explore the [reference documentation](https://docs.rs/shopify_function/latest/shopify_function/) for the `shopify_function` Rust crate.