Crates.io | ssr_rs |
lib.rs | ssr_rs |
version | 0.7.0 |
source | src |
created_at | 2021-05-01 11:49:59.120493 |
updated_at | 2024-10-11 09:10:51.605115 |
description | Server side rendering with the v8 engine for parse and evaluate the javascript code |
homepage | https://github.com/Valerioageno/ssr-rs |
repository | https://github.com/Valerioageno/ssr-rs |
max_upload_size | |
id | 391856 |
size | 153,203 |
The crate aims to enable server side rendering on rust servers in the simplest and lightest way possible.
It uses an embedded version of the V8 javascript engine (rusty_v8) to parse and evaluate a built bundle file and return a string with the rendered html.
[!NOTE] This project is the backbone of tuono; a fullstack react framework with built in SSR.
Currently it works with Vite, Webpack, Rspack, React 18 and Svelte 4 - Check the examples/
folder.
Check here the benchmark results.
Add this to your Cargo.toml
:
cargo add ssr_rs
To render to string a bundled react project the application should perform the following calls.
use ssr_rs::Ssr;
use std::fs::read_to_string;
fn main() {
Ssr::create_platform();
let source = read_to_string("./path/to/build.js").unwrap();
let mut js = Ssr::new(&source, "entryPoint").unwrap();
let html = js.render_to_string(None).unwrap();
assert_eq!(html, "<!doctype html><html>...</html>".to_string());
}
The entryPoint
could be either:
In case the bundled JS is an IIFE or the plain object the entryPoint
is an empty string.
// IIFE example | bundle.js -> See vite-react example
(() => ({ renderToStringFn: (props) => "<html></html>" }))() // The entryPoint is an empty string
// Plain object example | bundle.js
({renderToStringFn: (props) => "<html></html>"}); // The entryPoint is an empty string
// IIFE variable example | bundle.js -> See webpack-react example
var SSR = (() => ({renderToStringFn: (props) => "<html></html>"}))() // SSR is the entry point
// Variable example | bundle.js -> See webpack-react example
var SSR = {renderToStringFn: (props) => "<html></html>"}; // SSR is the entry point
The export results are managed by the bundler directly.
use ssr_rs::Ssr;
use std::fs::read_to_string;
fn main() {
Ssr::create_platform();
let props = r##"{
"params": [
"hello",
"ciao",
"ใใใซใกใฏ"
]
}"##;
let source = read_to_string("./path/to/build.js").unwrap();
let mut js = Ssr::new(&source, "entryPoint").unwrap();
let html = js.render_to_string(Some(&props)).unwrap();
assert_eq!(html, "<!doctype html><html>...</html>".to_string());
}
Examples with different web frameworks are available in the examples folder.
Even though the V8 engine allows accessing the same isolate
from different threads that is forbidden by this crate for two reasons:
For the reasons above parallel computation is a better choice. Following actix-web setup:
use actix_web::{get, http::StatusCode, App, HttpResponse, HttpServer};
use std::cell::RefCell;
use std::fs::read_to_string;
use ssr_rs::Ssr;
thread_local! {
static SSR: RefCell<Ssr<'static, 'static>> = RefCell::new(
Ssr::from(
read_to_string("./client/dist/ssr/index.js").unwrap(),
"SSR"
).unwrap()
)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
Ssr::create_platform();
HttpServer::new(|| {
App::new()
.service(index)
})
.bind("127.0.0.1:8080")?
.run()
.await
}
#[get("/")]
async fn index() -> HttpResponse {
let result = SSR.with(|ssr| ssr.borrow_mut().render_to_string(None).unwrap());
HttpResponse::build(StatusCode::OK)
.content_type("text/html; charset=utf-8")
.body(result)
}
Any helps or suggestions will be appreciated.
Known TODOs:
This project is licensed under the MIT License - see the LICENSE_MIT || LICENSE_APACHE file for more information.