Add a New Rust Project

The code for this example is available on GitHub:

Supported Features

We'll be using an Nx Plugin for Rust called @monodon/rust.

โœ… Run Tasks โœ… Cache Task Results โœ… Share Your Cache โœ… Explore the Graph โœ… Distribute Task Execution โœ… Integrate with Editors โœ… Automate Updating Nx โœ… Enforce Module Boundaries โœ… Use Task Executors โœ… Use Code Generators โœ… Automate Updating Framework Dependencies

Create the workspace with the @monodon/rust preset

We'll use the preset created by the @monodon/rust plugin to create the workspace with everything we need to build Rust applications.

โฏ

npx -y create-nx-workspace@latest acme --preset=@monodon/rust

Using the preset provided by @monodon/rust will:

  • Remove any unnecessary configuration files for working with Rust projects, such as tsconfig.json and .prettierrc
  • Remove unnecessary dependencies, such as @nx/js, as we're working with a Rust project
  • Add a root Cargo.toml to manage workspace members

Create the application

Let's generate a new application using @monodon/rust.

Directory Flag Behavior Changes

The command below uses the as-provided directory flag behavior, which is the default in Nx 16.8.0. If you're on an earlier version of Nx or using the derived option, omit the --directory flag. See the as-provided vs. derived documentation for more details.

โฏ

nx g @monodon/rust:binary myapp --directory=apps/myapp

Create a library

Let's generate a new library using @monodon/rust.

Directory Flag Behavior Changes

The command below uses the as-provided directory flag behavior, which is the default in Nx 16.8.0. If you're on an earlier version of Nx or using the derived option, omit the --directory flag. See the as-provided vs. derived documentation for more details.

โฏ

nx g @monodon/rust:library cats --directory=libs/cats

Update the cats library

First, let's update the Cargo.toml file to define the dependencies for the library.

libs/cats/Cargo.toml
1[package] 2name = "cats" 3version = "0.1.0" 4edition = "2021" 5 6[dependencies] 7actix-web = "4" 8 9[dependencies.serde] 10version = "1" 11features = ["derive"] 12 13# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 14

Now, let's add the code to handle the cats route.

libs/cats/src/lib.rs
1use std::collections::HashSet; 2use std::sync::Mutex; 3 4use actix_web::web::*; 5use actix_web::{get, post, HttpResponse, Responder, Scope}; 6 7pub struct Cats { 8 cats: Mutex<HashSet<Cat>>, 9} 10 11#[derive(Eq, Hash, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize)] 12struct Cat { 13 name: String, 14 age: u8, 15} 16 17#[get("")] 18async fn get_cats(data: Data<Cats>) -> impl Responder { 19 let cats = data.cats.lock().unwrap(); 20 21 println!("Cats {:?}", &cats); 22 23 Json(cats.clone()) 24} 25 26#[post("/add")] 27async fn add_cat(cat: Json<Cat>, data: Data<Cats>) -> impl Responder { 28 let mut cats = data.cats.lock().unwrap(); 29 30 println!("Adding {:?}", &cat); 31 32 cats.insert(cat.into_inner()); 33 34 HttpResponse::Ok() 35} 36 37pub fn create_cat_data() -> Data<Cats> { 38 Data::new(Cats { 39 cats: Mutex::new(HashSet::new()), 40 }) 41} 42 43pub fn create_cat_scope(data: &Data<Cats>) -> Scope { 44 scope("/cats") 45 // Cloning is cheap here because internally, Data uses `Arc` 46 .app_data(Data::clone(data)) 47 .service(add_cat) 48 .service(get_cats) 49} 50 51#[cfg(test)] 52mod tests { 53 #[test] 54 fn it_works() { 55 let result = 2 + 2; 56 assert_eq!(result, 4); 57 } 58} 59 60

Update the application

Let's create the http-server application and use the library to add the cats route.

First, we need to update the Cargo.toml file to define the application's dependencies.

apps/myapp/Cargo.toml
1[package] 2name = "myapp" 3version = "0.1.0" 4edition = "2021" 5 6 7[dependencies] 8actix-web = "4" 9cats = { path = "../../libs/cats" } 10 11 12# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 13 14

Now, let's update the application's code itself.

apps/myapp/src/main.rs
1use actix_web::{App, HttpServer}; 2 3use cats::{create_cat_data, create_cat_scope}; 4 5#[actix_web::main] 6async fn main() -> std::io::Result<()> { 7 // HttpServer:new creates multiple threads to handle requests. 8 // We need to make sure that the shared cat data is created once before the HttpServer 9 // We can then pass this reference to the create_cat_scope so that all threads have access to the same data 10 let cat_data = create_cat_data(); 11 HttpServer::new(move || App::new().service(create_cat_scope(&cat_data))) 12 .bind(("127.0.0.1", 8080))? 13 .run() 14 .await 15} 16 17

Build and Run the Application

To run the application, run the following command and then navigate your browser to http://localhost:8080/cats

โฏ

nx run myapp:run

To build the application, run the following command:

โฏ

nx build myapp

More Documentation