make fullstack hello world compile
This commit is contained in:
1 parent
499e81fa82
commit
ae3e167cfe
19 files changed
+288
-155
No files matched your search
@@ -7,8 +7,7 @@ publish = false
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dioxus = { workspace = true }
|
||||
dioxus-fullstack = { workspace = true }
|
||||
dioxus = { workspace = true, features = ["fullstack"]}
|
||||
serde = "1.0.159"
|
||||
simple_logger = "4.2.0"
|
||||
tracing-wasm = "0.2.1"
|
||||
@@ -18,5 +17,5 @@ reqwest = "0.11.18"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
ssr = ["dioxus-fullstack/axum"]
|
||||
web = ["dioxus-fullstack/web"]
|
||||
ssr = ["dioxus/axum"]
|
||||
web = ["dioxus/web"]
|
||||
@@ -7,27 +7,17 @@
|
||||
|
||||
#![allow(non_snake_case, unused)]
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_fullstack::{
|
||||
launch::{self, LaunchBuilder},
|
||||
prelude::*,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Props, PartialEq, Debug, Default, Serialize, Deserialize, Clone)]
|
||||
struct AppProps {
|
||||
count: i32,
|
||||
}
|
||||
|
||||
fn app(cx: Scope<AppProps>) -> Element {
|
||||
let state =
|
||||
use_server_future((), |()| async move { get_server_data().await.unwrap() })?.value();
|
||||
fn app() -> Element {
|
||||
// let state = use_server_future(|| async move { get_server_data().await.unwrap() })?;
|
||||
// let state = state.value();
|
||||
|
||||
let mut count = use_signal(|| 0);
|
||||
let text = use_signal(|| "...".to_string());
|
||||
let eval = use_eval(cx);
|
||||
|
||||
rsx! {
|
||||
div { "Server state: {state}" }
|
||||
// div { "Server state: {state}" }
|
||||
h1 { "High-Five counter: {count}" }
|
||||
button { onclick: move |_| count += 1, "Up high!" }
|
||||
button { onclick: move |_| count -= 1, "Down low!" }
|
||||
@@ -50,9 +40,7 @@ fn app(cx: Scope<AppProps>) -> Element {
|
||||
|
||||
#[server]
|
||||
async fn post_server_data(data: String) -> Result<(), ServerFnError> {
|
||||
let axum::extract::Host(host): axum::extract::Host = extract().await?;
|
||||
println!("Server received: {}", data);
|
||||
println!("{:?}", host);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -68,5 +56,5 @@ fn main() {
|
||||
#[cfg(feature = "ssr")]
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
LaunchBuilder::new_with_props(app, AppProps { count: 0 }).launch()
|
||||
launch(app);
|
||||
}
|
||||
@@ -63,6 +63,7 @@ use axum::{
|
||||
routing::{get, post},
|
||||
Router,
|
||||
};
|
||||
use dioxus_lib::prelude::dioxus_core::{AnyProps, CrossPlatformConfig};
|
||||
use server_fn::{Encoding, ServerFunctionRegistry};
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
@@ -215,10 +216,11 @@ pub trait DioxusRouterExt<S> {
|
||||
/// todo!()
|
||||
/// }
|
||||
/// ```
|
||||
fn serve_dioxus_application<P: Clone + serde::Serialize + Send + Sync + 'static>(
|
||||
fn serve_dioxus_application<P: AnyProps + Clone + Send + Sync + 'static>(
|
||||
self,
|
||||
server_fn_route: &'static str,
|
||||
cfg: impl Into<ServeConfig<P>>,
|
||||
cfg: impl Into<ServeConfig>,
|
||||
dioxus_config: CrossPlatformConfig<P>,
|
||||
) -> Self;
|
||||
}
|
||||
|
||||
@@ -313,10 +315,11 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
fn serve_dioxus_application<P: Clone + serde::Serialize + Send + Sync + 'static>(
|
||||
fn serve_dioxus_application<P: AnyProps + Clone + Send + Sync + 'static>(
|
||||
self,
|
||||
server_fn_route: &'static str,
|
||||
cfg: impl Into<ServeConfig<P>>,
|
||||
cfg: impl Into<ServeConfig>,
|
||||
dioxus_config: CrossPlatformConfig<P>,
|
||||
) -> Self {
|
||||
let cfg = cfg.into();
|
||||
let ssr_state = SSRState::new(&cfg);
|
||||
@@ -325,7 +328,7 @@ where
|
||||
self.serve_static_assets(cfg.assets_path)
|
||||
.connect_hot_reload()
|
||||
.register_server_fns(server_fn_route)
|
||||
.fallback(get(render_handler).with_state((cfg, ssr_state)))
|
||||
.fallback(get(render_handler).with_state((cfg, dioxus_config, ssr_state)))
|
||||
}
|
||||
|
||||
fn connect_hot_reload(self) -> Self {
|
||||
@@ -416,10 +419,15 @@ fn apply_request_parts_to_response<B>(
|
||||
/// }
|
||||
/// ```
|
||||
pub async fn render_handler_with_context<
|
||||
P: Clone + serde::Serialize + Send + Sync + 'static,
|
||||
P: AnyProps + Clone + Send + Sync + 'static,
|
||||
F: FnMut(&mut DioxusServerContext),
|
||||
>(
|
||||
State((mut inject_context, cfg, ssr_state)): State<(F, ServeConfig<P>, SSRState)>,
|
||||
State((mut inject_context, cfg, ssr_state, dioxus_config)): State<(
|
||||
F,
|
||||
ServeConfig,
|
||||
SSRState,
|
||||
CrossPlatformConfig<P>,
|
||||
)>,
|
||||
request: Request<Body>,
|
||||
) -> impl IntoResponse {
|
||||
let (parts, _) = request.into_parts();
|
||||
@@ -428,7 +436,10 @@ pub async fn render_handler_with_context<
|
||||
let mut server_context = DioxusServerContext::new(parts.clone());
|
||||
inject_context(&mut server_context);
|
||||
|
||||
match ssr_state.render(url, &cfg, &server_context).await {
|
||||
match ssr_state
|
||||
.render(url, &cfg, dioxus_config, &server_context)
|
||||
.await
|
||||
{
|
||||
Ok(rendered) => {
|
||||
let crate::render::RenderResponse { html, freshness } = rendered;
|
||||
let mut response = axum::response::Html::from(html).into_response();
|
||||
@@ -445,11 +456,15 @@ pub async fn render_handler_with_context<
|
||||
}
|
||||
|
||||
/// SSR renderer handler for Axum
|
||||
pub async fn render_handler<P: Clone + serde::Serialize + Send + Sync + 'static>(
|
||||
State((cfg, ssr_state)): State<(ServeConfig<P>, SSRState)>,
|
||||
pub async fn render_handler<P: AnyProps + Clone + Send + Sync + 'static>(
|
||||
State((cfg, dioxus_config, ssr_state)): State<(ServeConfig, CrossPlatformConfig<P>, SSRState)>,
|
||||
request: Request<Body>,
|
||||
) -> impl IntoResponse {
|
||||
render_handler_with_context(State((|_: &mut _| (), cfg, ssr_state)), request).await
|
||||
render_handler_with_context(
|
||||
State((|_: &mut _| (), cfg, ssr_state, dioxus_config)),
|
||||
request,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
fn report_err<E: std::fmt::Display>(e: E) -> Response<BoxBody> {
|
||||
|
||||
@@ -1,17 +1,34 @@
|
||||
//! Launch helper macros for fullstack apps
|
||||
#![allow(unused)]
|
||||
use crate::prelude::*;
|
||||
use dioxus_lib::prelude::{dioxus_core::AnyProps, *};
|
||||
use dioxus_lib::prelude::{
|
||||
dioxus_core::{AnyProps, CrossPlatformConfig},
|
||||
*,
|
||||
};
|
||||
|
||||
/// The desktop renderer platform
|
||||
pub struct FullstackPlatform;
|
||||
|
||||
impl<Props: AnyProps + Send + Sync + 'static> dioxus_core::PlatformBuilder<Props>
|
||||
impl<Props: AnyProps + Clone + Send + Sync + 'static> dioxus_core::PlatformBuilder<Props>
|
||||
for FullstackPlatform
|
||||
{
|
||||
type Config = Config;
|
||||
|
||||
fn launch(config: dioxus_core::CrossPlatformConfig<Props>, platform_config: Self::Config) {}
|
||||
fn launch(config: dioxus_core::CrossPlatformConfig<Props>, platform_config: Self::Config) {
|
||||
#[cfg(feature = "ssr")]
|
||||
tokio::runtime::Runtime::new()
|
||||
.unwrap()
|
||||
.block_on(async move {
|
||||
platform_config.launch_server(config).await;
|
||||
});
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
{
|
||||
#[cfg(feature = "web")]
|
||||
platform_config.launch_web(config);
|
||||
#[cfg(feature = "desktop")]
|
||||
platform_config.launch_desktop(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Settings for a fullstack app.
|
||||
@@ -99,31 +116,33 @@ impl Config {
|
||||
}
|
||||
|
||||
/// Launch the app.
|
||||
pub fn launch(self) {
|
||||
pub fn launch<P: AnyProps + Clone + Send + Sync>(self, dioxus_config: CrossPlatformConfig<P>) {
|
||||
#[cfg(feature = "ssr")]
|
||||
tokio::runtime::Runtime::new()
|
||||
.unwrap()
|
||||
.block_on(async move {
|
||||
self.launch_server().await;
|
||||
self.launch_server(dioxus_config).await;
|
||||
});
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
{
|
||||
#[cfg(feature = "web")]
|
||||
self.launch_web();
|
||||
self.launch_web(dioxus_config);
|
||||
#[cfg(feature = "desktop")]
|
||||
self.launch_desktop();
|
||||
self.launch_desktop(dioxus_config);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "web")]
|
||||
/// Launch the web application
|
||||
pub fn launch_web(self) {
|
||||
pub fn launch_web<P: AnyProps>(self, dioxus_config: CrossPlatformConfig<P>) {
|
||||
use dioxus_lib::prelude::dioxus_core::{CrossPlatformConfig, PlatformBuilder};
|
||||
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
{
|
||||
let cfg = self.web_cfg.hydrate(true);
|
||||
dioxus_web::launch_with_props(
|
||||
self.component,
|
||||
get_root_props_from_document().unwrap(),
|
||||
dioxus_web::WebPlatform::launch(
|
||||
// TODO: this should pull the props from the document
|
||||
dioxus_config,
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
@@ -131,14 +150,17 @@ impl Config {
|
||||
|
||||
#[cfg(feature = "desktop")]
|
||||
/// Launch the web application
|
||||
pub fn launch_desktop(self) {
|
||||
pub fn launch_desktop<P: AnyProps>(self, dioxus_config: CrossPlatformConfig<P>) {
|
||||
let cfg = self.desktop_cfg;
|
||||
dioxus_desktop::launch_with_props(self.component, self.props, cfg);
|
||||
}
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
/// Launch a server application
|
||||
pub async fn launch_server(self) {
|
||||
pub async fn launch_server<P: AnyProps + Send + Sync + Clone>(
|
||||
self,
|
||||
dioxus_config: CrossPlatformConfig<P>,
|
||||
) {
|
||||
let addr = self.addr;
|
||||
println!("Listening on {}", addr);
|
||||
let cfg = self.server_cfg.build();
|
||||
@@ -155,7 +177,7 @@ impl Config {
|
||||
let router = router
|
||||
.serve_static_assets(cfg.assets_path)
|
||||
.connect_hot_reload()
|
||||
.fallback(get(render_handler).with_state((cfg, ssr_state)));
|
||||
.fallback(get(render_handler).with_state((cfg, dioxus_config, ssr_state)));
|
||||
let router = router
|
||||
.layer(
|
||||
ServiceBuilder::new()
|
||||
|
||||
@@ -14,7 +14,8 @@ pub use adapters::*;
|
||||
mod hooks;
|
||||
#[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
|
||||
mod hot_reload;
|
||||
pub mod launch;
|
||||
mod launch;
|
||||
pub use launch::*;
|
||||
#[cfg(feature = "ssr")]
|
||||
mod layer;
|
||||
#[cfg(feature = "ssr")]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//! A shared pool of renderers for efficient server side rendering.
|
||||
|
||||
use crate::render::dioxus_core::AnyProps;
|
||||
use crate::render::dioxus_core::CrossPlatformConfig;
|
||||
use crate::render::dioxus_core::NoOpMutations;
|
||||
use crate::server_context::SERVER_CONTEXT;
|
||||
use dioxus_lib::prelude::VirtualDom;
|
||||
@@ -21,15 +22,15 @@ enum SsrRendererPool {
|
||||
}
|
||||
|
||||
impl SsrRendererPool {
|
||||
async fn render_to<P: Clone + Serialize + Send + Sync + 'static>(
|
||||
async fn render_to<P: AnyProps + Clone + Send + Sync + 'static>(
|
||||
&self,
|
||||
cfg: &ServeConfig<P>,
|
||||
cfg: &ServeConfig,
|
||||
route: String,
|
||||
component: Component<P>,
|
||||
props: P,
|
||||
dioxus_config: CrossPlatformConfig<P>,
|
||||
server_context: &DioxusServerContext,
|
||||
) -> Result<(RenderFreshness, String), dioxus_ssr::incremental::IncrementalRendererError> {
|
||||
let wrapper = FullstackRenderer {
|
||||
serialized_props: None,
|
||||
cfg: cfg.clone(),
|
||||
server_context: server_context.clone(),
|
||||
};
|
||||
@@ -44,7 +45,7 @@ impl SsrRendererPool {
|
||||
tokio::runtime::Runtime::new()
|
||||
.expect("couldn't spawn runtime")
|
||||
.block_on(async move {
|
||||
let mut vdom = VirtualDom::new_with_props(component, props);
|
||||
let mut vdom = dioxus_config.build_vdom();
|
||||
vdom.in_runtime(|| {
|
||||
// Make sure the evaluator is initialized
|
||||
dioxus_ssr::eval::init_eval();
|
||||
@@ -111,8 +112,7 @@ impl SsrRendererPool {
|
||||
match renderer
|
||||
.render(
|
||||
route,
|
||||
component,
|
||||
props,
|
||||
dioxus_config,
|
||||
&mut *to,
|
||||
|vdom| {
|
||||
Box::pin(async move {
|
||||
@@ -169,7 +169,7 @@ pub struct SSRState {
|
||||
|
||||
impl SSRState {
|
||||
/// Create a new [`SSRState`].
|
||||
pub fn new<P: Clone>(cfg: &ServeConfig<P>) -> Self {
|
||||
pub fn new(cfg: &ServeConfig) -> Self {
|
||||
if cfg.incremental.is_some() {
|
||||
return Self {
|
||||
renderers: Arc::new(SsrRendererPool::Incremental(RwLock::new(vec![
|
||||
@@ -192,13 +192,12 @@ impl SSRState {
|
||||
}
|
||||
|
||||
/// Render the application to HTML.
|
||||
pub fn render<'a, P: 'static + Clone + serde::Serialize + Send + Sync>(
|
||||
pub fn render<'a, P: AnyProps + Clone + Send + Sync>(
|
||||
&'a self,
|
||||
route: String,
|
||||
cfg: &'a ServeConfig<P>,
|
||||
cfg: &'a ServeConfig,
|
||||
dioxus_config: CrossPlatformConfig<P>,
|
||||
server_context: &'a DioxusServerContext,
|
||||
app: Component<P>,
|
||||
props: P,
|
||||
) -> impl std::future::Future<
|
||||
Output = Result<RenderResponse, dioxus_ssr::incremental::IncrementalRendererError>,
|
||||
> + Send
|
||||
@@ -208,7 +207,7 @@ impl SSRState {
|
||||
|
||||
let (freshness, html) = self
|
||||
.renderers
|
||||
.render_to(cfg, route, app, props, server_context)
|
||||
.render_to(cfg, route, dioxus_config, server_context)
|
||||
.await?;
|
||||
|
||||
Ok(RenderResponse { html, freshness })
|
||||
@@ -216,16 +215,13 @@ impl SSRState {
|
||||
}
|
||||
}
|
||||
|
||||
struct FullstackRenderer<P: Clone + Send + Sync + 'static> {
|
||||
component: Component<P>,
|
||||
props: P,
|
||||
struct FullstackRenderer {
|
||||
serialized_props: Option<String>,
|
||||
cfg: ServeConfig,
|
||||
server_context: DioxusServerContext,
|
||||
}
|
||||
|
||||
impl<P: Clone + Serialize + Send + Sync + 'static> dioxus_ssr::incremental::WrapBody
|
||||
for FullstackRenderer<P>
|
||||
{
|
||||
impl dioxus_ssr::incremental::WrapBody for FullstackRenderer {
|
||||
fn render_before_body<R: std::io::Write>(
|
||||
&self,
|
||||
to: &mut R,
|
||||
@@ -242,9 +238,10 @@ impl<P: Clone + Serialize + Send + Sync + 'static> dioxus_ssr::incremental::Wrap
|
||||
to: &mut R,
|
||||
) -> Result<(), dioxus_ssr::incremental::IncrementalRendererError> {
|
||||
// serialize the props
|
||||
crate::html_storage::serialize::encode_props_in_element(&self.cfg.props, to).map_err(
|
||||
|err| dioxus_ssr::incremental::IncrementalRendererError::Other(Box::new(err)),
|
||||
)?;
|
||||
// TODO: restore props serialization
|
||||
// crate::html_storage::serialize::encode_props_in_element(&self.cfg.props, to).map_err(
|
||||
// |err| dioxus_ssr::incremental::IncrementalRendererError::Other(Box::new(err)),
|
||||
// )?;
|
||||
// serialize the server state
|
||||
crate::html_storage::serialize::encode_in_element(
|
||||
&*self.server_context.html_data().map_err(|_| {
|
||||
|
||||
Reference in new issue
Block a user