How to pass environment variables to a Rust WASM application like Yew, Dioxus and Leptos as a TypeScript Developer
Tags: webdev, typescript, rust, webassembly
Published: 2023-07-10 17:45:03

Hello TypeStaceans!

Here's a step by step process in how you can pass environment variables to a Rust WASM application framework using Yew, Dioxus, Leptos, Sycamore, or your favorite one. 

**GitHub Repo**
TypeStacean - [Learn Rust WASM from TypeScript](https://github.com/superjose/typestacean-learn-rust-wasm-from-typescript)

## How you do it in TypeScript

Given a TypeScript React, Vue, Svelte, or Vanilla TypeScript app, you'd generally have an .env at the root level of your project:

```env
APP_S3_URL="https://aws.amazon.com"
APP_AUTH0_ID="asdk211jrifenf"
APP_OTHER_NON_SENSIBLE_INFO="h123213"
```
And then, you could either augment it in a .d.ts file or create an object and expose it.

```env
declare global {
  namespace NodeJS {
    interface ProcessEnv {
      APP_S3_URL: string;
      APP_AUTH0_ID: string;
      APP_OTHER_NON_SENSIBLE_INFO: string;
    }
  }
}
```

This .env would then be injected at **build time.**

It isn't possible to pass it as runtime (unless you fetch it from an external resource) as you need to run a process for it do so.

In Web Assembly, things are the same. 

## Environment Variables in Rust Web Assembly (Yew, Dioxus, Leptos).
In WebAssembly we need to pass the environment variable at compile time. 

Therefore we cannot use the [`dotenv`](https://crates.io/crates/dotenv) crate (similar to npm's [dotenv](https://www.npmjs.com/package/dotenv)) as it's only available in runtime.

We will leverage Rust's built-in build.rs script system to read the environment at build time and then generate a custom .rs file which we can read afterwards. 

> Never store server-sensitive information in your front-end .env files as these are accessible to the public

## Using build.rs to inject the environment variables.

1. Go to the root of your project and create an empty `build.rs` file and an empty .env file.


![Root Directory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p8xidg0xlruwlsuy8lfp.png)

2. Add `dotenv` to the build-dependencies part of `Cargo.Toml`
```toml
[package]
name = "typestacean-learn-rust-wasm-from-typescript"
version = "0.1.0"
edition = "2021"

## Add these:
[build-dependencies]
dotenv = "0.15.0"
```
This will enable dotenv to be used in `build.rs`

3. Fill in the build.rs script
```rust
// build.rs
use dotenv::dotenv;
use std::env;
use std::fs::File;
use std::io::Write;

fn main() {
    println!("cargo:rerun-if-changed=.env");
    let dest_path = "./src/env.rs";
    let mut f = File::create(&dest_path).unwrap();

    // use the dotenv crate to get the .env values
    dotenv().ok();
    f.write_all(b"// This file is automatically generated by build.rs\n\n")
        .unwrap()
    for (key, value) in env::vars() {
        if key.starts_with("APP_") {
            let line = format!(
                "pub const {}: &'static str = \"{}\";\n",
                key,
                value.replace("\"", "\\\"")
            );
            f.write_all(line.as_bytes()).unwrap();
        }
    }
}
```

**Here's the breakdown:**
* We define a main() function that will be used as the entry point
* The `println!("cargo:rerun-if-changed=.env");` tells cargo to prevent running the build.rs script if the `.env` file hasn't changed. 
* We then set to generate `env.rs` in `src/env.rs`
* We then call `dotenv().ok()` to load the environment from the .env to the  `env::vars()`. 
* The `b""` means that the strings should be represented as a sequence of bytes.
* We iterate the environment line per line, we process it so we can generate something like:
```
pub const APP_WASM_FRAMEWORK: &'static str = "leptos";
```
* This is then written in the env.rs file

## Include the .env.rs file in your script
```rust
// Other imports omitted
mod env;

fn main() {
   println!("{}", env::APP_WASM_FRAMEWORK);
}

```



## Feedback appreciated


## Follow to learn Rust WASM as an experienced TypeScript developer
I'm currently learning and sharing my knowledge with Rust's most popular WASM frameworks: Yew, Dioxus, Leptos.

I want to help TypeStaceans (TypeScript developers who want to learn Rust Web Assembly) to grasp Rust WASM as fast as possible by sharing the distilled knowledge.

Follow me on:

* dev.to - https://dev.to/javiasilis
* twitter - https://twitter.com/javiasilis
* linkedin - https://linkedin.com/in/javiasilis