{"id":13550101,"url":"https://github.com/Pitasi/rscx","last_synced_at":"2025-04-02T23:31:47.845Z","repository":{"id":193044480,"uuid":"688002729","full_name":"Pitasi/rscx","owner":"Pitasi","description":"Rust Server Components. JSX-like syntax and async out of the box.","archived":false,"fork":false,"pushed_at":"2024-02-15T20:46:04.000Z","size":71,"stargazers_count":65,"open_issues_count":4,"forks_count":6,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-05T07:55:28.951Z","etag":null,"topics":["hacktoberfest","rscx","rust","web"],"latest_commit_sha":null,"homepage":"https://rscx.dev/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Pitasi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-06T12:57:18.000Z","updated_at":"2025-02-16T15:36:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"5a31e077-0c57-4ac3-b9b0-061c146da733","html_url":"https://github.com/Pitasi/rscx","commit_stats":null,"previous_names":["pitasi/rscx"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pitasi%2Frscx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pitasi%2Frscx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pitasi%2Frscx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pitasi%2Frscx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Pitasi","download_url":"https://codeload.github.com/Pitasi/rscx/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246911128,"owners_count":20853653,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","rscx","rust","web"],"created_at":"2024-08-01T12:01:28.958Z","updated_at":"2025-04-02T23:31:47.511Z","avatar_url":"https://github.com/Pitasi.png","language":"Rust","readme":"![crates.io](https://img.shields.io/crates/v/rscx.svg)\n\n# RSCx - Rust Server Components\n\nRSCx is a server-side HTML rendering engine library with a neat developer\nexperience and great performance.\n\nFeatures:\n\n- all components are async functions\n- JSX-like syntax called RSX parsed with [rstml](https://github.com/rs-tml/rstml)\n- contexts, to easily pass values down the components tree ([example](https://github.com/Pitasi/rscx/blob/main/rscx/examples/context.rs))\n- inspired by [Maud](https://maud.lambda.xyz/) and [Leptos](https://leptos.dev/)\n\n*⚠️ Warning: not production-ready yet. It lacks important features such as HTML\nescaping!*\n\n\n## Usage\n\nAll the examples can be found in [rscx/examples/](https://github.com/Pitasi/rscx/tree/main/rscx/examples).\n\n```rs\nuse rscx::{component, html, props, CollectFragment};\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let app = app().await;\n    println!(\"{}\", app);\n    Ok(())\n}\n\n// simple function returning a String\n// it will call the Items() function\nasync fn app() -\u003e String {\n    let s = \"ul { color: red; }\";\n    html! {\n        \u003c!DOCTYPE html\u003e\n        \u003chtml\u003e\n            \u003chead\u003e\n                \u003cstyle\u003e{s}\u003c/style\u003e\n            \u003c/head\u003e\n            \u003cbody\u003e\n                // call a component with no props\n                \u003cSection /\u003e\n\n                // call a component with props and children\n                \u003cSection title=\"Hello\"\u003e\n                    \u003cItems /\u003e\n                \u003c/Section\u003e\n            \u003c/body\u003e\n        \u003c/html\u003e\n    }\n}\n\n#[component]\n/// mark functions with #[component] to use them as components inside html! macro\nfn Section(\n    // you can use `builder` attributes to specify a default value (makes this prop optional)\n    #[builder(default = \"Default title\".into(), setter(into))] title: String,\n    #[builder(default)] children: String,\n) -\u003e String {\n    html! {\n        \u003cdiv\u003e\n            \u003ch1\u003e{ title }\u003c/h1\u003e\n            { children }\n        \u003c/div\u003e\n    }\n}\n\n#[component]\nasync fn Items() -\u003e String {\n    let data = load_data_async().await;\n    html! {\n        \u003cul\u003e\n            {\n                data\n                    .into_iter()\n                    .map(|item| html! { \u003cli\u003e{ item }\u003c/li\u003e })\n                    .collect_fragment() // helper method to collect a list of components into a String\n            }\n        \u003c/ul\u003e\n    }\n}\n\n/// async functions can be easily used in the body of a component, as every component is an async\n/// function\nasync fn load_data_async() -\u003e Vec\u003cString\u003e {\n    vec![\"a\".to_string(), \"b\".to_string(), \"c\".to_string()]\n}\n```\n\n\n## Benchmarks\n\nRSCx is fast.\n\n*Disclaimer*: RSCx is for servers, as the name suggests. Therefore the following\ncomparisons with Leptos are unfair. This library contains only a fraction of\nLeptos' features.\n\n*Disclaimer 2*: The benchmarks are pretty basics and should not influence your\ndecision on whether to use or not this library. Focus on the DX. They are\nincluded as I kept running them to make sure I didn't fall too much behind\nalternatives.\n\nThe time in the middle of the three is the average.\n\n### Run the benchmarks locally\n\n```\ncd bench\n# cargo install criterion\ncargo criterion\n```\n\n\n### Benchmark 1: single element, lots of HTML attributes\n\n```\nmany_attrs/maud_many_attrs\n                        time:   [205.89 ns 208.35 ns 211.53 ns]\nmany_attrs/horrorshow_many_attrs\n                        time:   [37.221 µs 37.304 µs 37.401 µs]\nmany_attrs/html_node_many_attrs\n                        time:   [67.726 µs 67.830 µs 67.939 µs]\nmany_attrs/leptos_many_attrs\n                        time:   [923.31 ns 928.46 ns 935.04 ns]\nmany_attrs/rscx_many_attrs\n                        time:   [207.96 ns 212.82 ns 219.28 ns]\n```\n\nRSCx and Maud pretty much are the same as their macros output is effectively a\nstatic string with the result.\n\n\n### Benchmark 2: little element with props and child\n\n```\nsmall_fragment/maud_small_fragment\n                        time:   [107.60 ns 107.71 ns 107.81 ns]\nsmall_fragment/horrorshow_small_fragment\n                        time:   [405.98 ns 406.08 ns 406.21 ns]\nsmall_fragment/leptos_small_fragment\n                        time:   [1.7641 µs 1.7652 µs 1.7662 µs]\nsmall_fragment/rscx_small_fragment\n                        time:   [101.79 ns 101.87 ns 101.97 ns]\n```\n\nRSCx offers a better DX than Maud, as the syntax is nicer and values such as i32\ncan be passed as props/attributes, while in Maud every attribute must be a\nstatic string.\n\n\n### Benchmark 3: dynamic attributes (read for variable)\n\n```\nmany_dyn_attrs/horrorshow_many_dyn_attrs\n                        time:   [50.445 µs 50.702 µs 50.977 µs]\nmany_dyn_attrs/leptos_many_dyn_attrs\n                        time:   [100.13 µs 100.52 µs 101.00 µs]\nmany_dyn_attrs/rscx_many_dyn_attrs\n                        time:   [33.953 µs 33.990 µs 34.037 µs]\n```\n\n\n### Benchmark 4: async component rendering a list of 100 items\n\n```\nasync_list/maud_async_list\n                        time:   [2.3114 µs 2.3241 µs 2.3377 µs]\nasync_list/leptos_async_list\n                        time:   [55.149 µs 55.228 µs 55.315 µs]\nasync_list/rscx_async_list\n                        time:   [5.4809 µs 5.4987 µs 5.5151 µs]\n```\n\nI'll reiterate the disclaimer: Leptos is not specifically made for SSR. Going\nthrough its reactivity system (using async resources) adds overhead.\n\n","funding_links":[],"categories":["Rust"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPitasi%2Frscx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FPitasi%2Frscx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPitasi%2Frscx/lists"}