Server-side rendering

    This article will explore how to render the web UI on the server using WasmEdge. We pick as our framework because it is relatively mature in SSR and Hydration). Percy already provides an for SSR. It’s highly recommended to read it first to understand how it works. The default SSR setup with Percy utilizes a native Rust web server. The Rust code is compiled to machine native code for the server. However, in order to host user applications on the server, we need a sandbox. While we could run native code inside a Linux container (Docker), a far more efficient (and safer) approach is to run the compiled code in a WebAssembly VM on the server, especially considerring the rendering code is already compiled into WebAssembly.

    Now, let’s go through the steps to run a Percy SSR service in a WasmEdge server.

    Assuming we are in the examples/isomorphic directory, make a new crate beside the existing server.

    cargo new server-wasmedge

    You’ll receive a warning to let you put the new crate into the workspace, so insert below into members of [workspace]. The file is ../../Cargo.toml.

    "examples/isomorphic/server-wasmedge"

    With the file open, put these two lines in the bottom:

    [patch.crates-io] wasm-bindgen = { git = "https://github.com/KernelErr/wasm-bindgen.git", branch = "wasi-compat" }

    Then replace the crate’s Cargo.toml with following content.

    [package] name = "isomorphic-server-wasmedge" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] wasmedge_wasi_socket = "0" querystring = "1.1.0" parsed = { version = "0.3", features = ["http"] } anyhow = "1" serde = { version = "1.0", features = ["derive"] } isomorphic-app = { path = "../app" }

    The wasmedge_wasi_socket crate is the socket API of WasmEdge. This project is under development. Next copy the index.html file into the crate’s root.

    cp server/src/index.html server-wasmedge/src/

    Then let’s create some Rust code to start a web service in WasmEdge! The main.rs program listens to the request and sends the response via the stream.

    The parses the received data to the path and query objects and return the corresponding response.

    The response.rs program packs the response object for static assets and for server rendered content. For the latter, you could see that SSR happens at app.render().to_string(), the result string is put into HTML by replacing the placeholder text.

    The mime.rs program is a map for assets’ extension name and the Mime type.

    That’s it! Now let’s build and run the web application. If you have tested the original example, you probably have already built the client WebAssembly.

    Next, build and run the server.

    cd ../server-wasmedge cargo build --target wasm32-wasi OUTPUT_CSS="$(pwd)/../client/build/app.css" wasmedge --dir /static:../client/build ../../../target/wasm32-wasi/debug/isomorphic-server-wasmedge.wasm

    Navigate to http://127.0.0.1:3000 and you will see the web application in action.

    Furthermore, you can place all the steps into a shell script ../start-wasmedge.sh.

    #!/bin/bash cd $(dirname $0) cd ./client ./build-wasm.sh cd ../server-wasmedge OUTPUT_CSS="$(pwd)/../client/build/app.css" cargo run -p isomorphic-server-wasmedge

    Add the following to the .cargo/config.toml file.

    [build] target = "wasm32-wasi" [target.wasm32-wasi] runner = "wasmedge --dir /static:../client/build"

    After that, a single CLI command would perform all the tasks to build and run the web application!

    We forked the Percy repository and made a ready-to-build server-wasmedge example project for you. Happy coding!