|
@@ -7,13 +7,33 @@ use dioxus_ssr::{
|
|
|
Renderer,
|
|
|
};
|
|
|
use serde::Serialize;
|
|
|
+use std::future::Future;
|
|
|
use std::sync::Arc;
|
|
|
use std::sync::RwLock;
|
|
|
-use tokio::task::spawn_blocking;
|
|
|
+use tokio::task::{spawn_blocking, JoinHandle};
|
|
|
|
|
|
use crate::prelude::*;
|
|
|
use dioxus_lib::prelude::*;
|
|
|
|
|
|
+fn spawn_platform<Fut>(f: impl FnOnce() -> Fut + Send + 'static) -> JoinHandle<Fut::Output>
|
|
|
+where
|
|
|
+ Fut: Future + 'static,
|
|
|
+ Fut::Output: Send + 'static,
|
|
|
+{
|
|
|
+ #[cfg(not(target_arch = "wasm32"))]
|
|
|
+ {
|
|
|
+ spawn_blocking(move || {
|
|
|
+ tokio::runtime::Runtime::new()
|
|
|
+ .expect("couldn't spawn runtime")
|
|
|
+ .block_on(f())
|
|
|
+ })
|
|
|
+ }
|
|
|
+ #[cfg(target_arch = "wasm32")]
|
|
|
+ {
|
|
|
+ tokio::task::spawn_local(f())
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
enum SsrRendererPool {
|
|
|
Renderer(RwLock<Vec<Renderer>>),
|
|
|
Incremental(RwLock<Vec<dioxus_ssr::incremental::IncrementalRenderer>>),
|
|
@@ -39,51 +59,41 @@ impl SsrRendererPool {
|
|
|
|
|
|
let (tx, rx) = tokio::sync::oneshot::channel();
|
|
|
|
|
|
- spawn_blocking(move || {
|
|
|
- tokio::runtime::Runtime::new()
|
|
|
- .expect("couldn't spawn runtime")
|
|
|
- .block_on(async move {
|
|
|
- let mut vdom = virtual_dom_factory();
|
|
|
- let mut to = WriteBuffer { buffer: Vec::new() };
|
|
|
- // before polling the future, we need to set the context
|
|
|
- let prev_context =
|
|
|
- SERVER_CONTEXT.with(|ctx| ctx.replace(server_context));
|
|
|
- // poll the future, which may call server_context()
|
|
|
- tracing::info!("Rebuilding vdom");
|
|
|
- let _ = vdom.rebuild(&mut NoOpMutations);
|
|
|
- vdom.wait_for_suspense().await;
|
|
|
- tracing::info!("Suspense resolved");
|
|
|
- // after polling the future, we need to restore the context
|
|
|
- SERVER_CONTEXT.with(|ctx| ctx.replace(prev_context));
|
|
|
-
|
|
|
- if let Err(err) = wrapper.render_before_body(&mut *to) {
|
|
|
- let _ = tx.send(Err(err));
|
|
|
- return;
|
|
|
- }
|
|
|
- if let Err(err) = renderer.render_to(&mut to, &vdom) {
|
|
|
- let _ = tx.send(Err(
|
|
|
- dioxus_ssr::incremental::IncrementalRendererError::RenderError(
|
|
|
- err,
|
|
|
- ),
|
|
|
- ));
|
|
|
- return;
|
|
|
- }
|
|
|
- if let Err(err) = wrapper.render_after_body(&mut *to) {
|
|
|
- let _ = tx.send(Err(err));
|
|
|
- return;
|
|
|
- }
|
|
|
- match String::from_utf8(to.buffer) {
|
|
|
- Ok(html) => {
|
|
|
- let _ =
|
|
|
- tx.send(Ok((renderer, RenderFreshness::now(None), html)));
|
|
|
- }
|
|
|
- Err(err) => {
|
|
|
- dioxus_ssr::incremental::IncrementalRendererError::Other(
|
|
|
- Box::new(err),
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
+ spawn_platform(move || async move {
|
|
|
+ let mut vdom = virtual_dom_factory();
|
|
|
+ let mut to = WriteBuffer { buffer: Vec::new() };
|
|
|
+ // before polling the future, we need to set the context
|
|
|
+ let prev_context = SERVER_CONTEXT.with(|ctx| ctx.replace(server_context));
|
|
|
+ // poll the future, which may call server_context()
|
|
|
+ tracing::info!("Rebuilding vdom");
|
|
|
+ let _ = vdom.rebuild(&mut NoOpMutations);
|
|
|
+ vdom.wait_for_suspense().await;
|
|
|
+ tracing::info!("Suspense resolved");
|
|
|
+ // after polling the future, we need to restore the context
|
|
|
+ SERVER_CONTEXT.with(|ctx| ctx.replace(prev_context));
|
|
|
+
|
|
|
+ if let Err(err) = wrapper.render_before_body(&mut *to) {
|
|
|
+ let _ = tx.send(Err(err));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if let Err(err) = renderer.render_to(&mut to, &vdom) {
|
|
|
+ let _ = tx.send(Err(
|
|
|
+ dioxus_ssr::incremental::IncrementalRendererError::RenderError(err),
|
|
|
+ ));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if let Err(err) = wrapper.render_after_body(&mut *to) {
|
|
|
+ let _ = tx.send(Err(err));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ match String::from_utf8(to.buffer) {
|
|
|
+ Ok(html) => {
|
|
|
+ let _ = tx.send(Ok((renderer, RenderFreshness::now(None), html)));
|
|
|
+ }
|
|
|
+ Err(err) => {
|
|
|
+ dioxus_ssr::incremental::IncrementalRendererError::Other(Box::new(err));
|
|
|
+ }
|
|
|
+ }
|
|
|
});
|
|
|
let (renderer, freshness, html) = rx.await.unwrap()?;
|
|
|
pool.write().unwrap().push(renderer);
|
|
@@ -98,53 +108,49 @@ impl SsrRendererPool {
|
|
|
let (tx, rx) = tokio::sync::oneshot::channel();
|
|
|
|
|
|
let server_context = server_context.clone();
|
|
|
- spawn_blocking(move || {
|
|
|
- tokio::runtime::Runtime::new()
|
|
|
- .expect("couldn't spawn runtime")
|
|
|
- .block_on(async move {
|
|
|
- let mut to = WriteBuffer { buffer: Vec::new() };
|
|
|
- match renderer
|
|
|
- .render(
|
|
|
- route,
|
|
|
- virtual_dom_factory,
|
|
|
- &mut *to,
|
|
|
- |vdom| {
|
|
|
- Box::pin(async move {
|
|
|
- // before polling the future, we need to set the context
|
|
|
- let prev_context = SERVER_CONTEXT
|
|
|
- .with(|ctx| ctx.replace(Box::new(server_context)));
|
|
|
- // poll the future, which may call server_context()
|
|
|
- tracing::info!("Rebuilding vdom");
|
|
|
- let _ = vdom.rebuild(&mut NoOpMutations);
|
|
|
- vdom.wait_for_suspense().await;
|
|
|
- tracing::info!("Suspense resolved");
|
|
|
- // after polling the future, we need to restore the context
|
|
|
- SERVER_CONTEXT.with(|ctx| ctx.replace(prev_context));
|
|
|
- })
|
|
|
- },
|
|
|
- &wrapper,
|
|
|
- )
|
|
|
- .await
|
|
|
- {
|
|
|
- Ok(freshness) => {
|
|
|
- match String::from_utf8(to.buffer).map_err(|err| {
|
|
|
- dioxus_ssr::incremental::IncrementalRendererError::Other(
|
|
|
- Box::new(err),
|
|
|
- )
|
|
|
- }) {
|
|
|
- Ok(html) => {
|
|
|
- let _ = tx.send(Ok((freshness, html)));
|
|
|
- }
|
|
|
- Err(err) => {
|
|
|
- let _ = tx.send(Err(err));
|
|
|
- }
|
|
|
- }
|
|
|
+ spawn_platform(move || async move {
|
|
|
+ let mut to = WriteBuffer { buffer: Vec::new() };
|
|
|
+ match renderer
|
|
|
+ .render(
|
|
|
+ route,
|
|
|
+ virtual_dom_factory,
|
|
|
+ &mut *to,
|
|
|
+ |vdom| {
|
|
|
+ Box::pin(async move {
|
|
|
+ // before polling the future, we need to set the context
|
|
|
+ let prev_context = SERVER_CONTEXT
|
|
|
+ .with(|ctx| ctx.replace(Box::new(server_context)));
|
|
|
+ // poll the future, which may call server_context()
|
|
|
+ tracing::info!("Rebuilding vdom");
|
|
|
+ let _ = vdom.rebuild(&mut NoOpMutations);
|
|
|
+ vdom.wait_for_suspense().await;
|
|
|
+ tracing::info!("Suspense resolved");
|
|
|
+ // after polling the future, we need to restore the context
|
|
|
+ SERVER_CONTEXT.with(|ctx| ctx.replace(prev_context));
|
|
|
+ })
|
|
|
+ },
|
|
|
+ &wrapper,
|
|
|
+ )
|
|
|
+ .await
|
|
|
+ {
|
|
|
+ Ok(freshness) => {
|
|
|
+ match String::from_utf8(to.buffer).map_err(|err| {
|
|
|
+ dioxus_ssr::incremental::IncrementalRendererError::Other(Box::new(
|
|
|
+ err,
|
|
|
+ ))
|
|
|
+ }) {
|
|
|
+ Ok(html) => {
|
|
|
+ let _ = tx.send(Ok((freshness, html)));
|
|
|
}
|
|
|
Err(err) => {
|
|
|
let _ = tx.send(Err(err));
|
|
|
}
|
|
|
}
|
|
|
- })
|
|
|
+ }
|
|
|
+ Err(err) => {
|
|
|
+ let _ = tx.send(Err(err));
|
|
|
+ }
|
|
|
+ }
|
|
|
});
|
|
|
let (freshness, html) = rx.await.unwrap()?;
|
|
|
|