router/fullstack/ssr intigration

This commit is contained in:
Evan Almloff committed 2023-06-22 16:51:48 -07:00
1 parent 495fd22bfd
commit 1704ee0068
21 files changed
+507 -203

No files matched your search

+78 -28
View File
@@ -2,53 +2,93 @@
use std::sync::Arc;
use dioxus_core::VirtualDom;
use dioxus_ssr::Renderer;
use dioxus::prelude::VirtualDom;
use dioxus_ssr::{incremental::IncrementalRendererConfig, Renderer};
use crate::prelude::ServeConfig;
use crate::prelude::*;
use dioxus::prelude::*;
enum SsrRendererPool {
Renderer(object_pool::Pool<Renderer>),
Incremental(
object_pool::Pool<
dioxus_ssr::incremental::IncrementalRenderer<
crate::serve_config::EmptyIncrementalRenderTemplate,
>,
>,
),
}
impl SsrRendererPool {
fn render_to<P: Clone + 'static>(
&self,
cfg: &ServeConfig<P>,
route: String,
component: Component<P>,
props: P,
to: &mut String,
modify_vdom: impl FnOnce(&mut VirtualDom),
) -> Result<(), dioxus_ssr::incremental::IncrementalRendererError> {
match self {
Self::Renderer(pool) => {
let mut vdom = VirtualDom::new_with_props(component, props);
let _ = vdom.rebuild();
let mut renderer = pool.pull(pre_renderer);
renderer.render_to(to, &vdom)?;
}
Self::Incremental(pool) => {
let mut renderer = pool.pull(|| incremental_pre_renderer(cfg));
renderer.render_to_string(route, component, props, to, modify_vdom)?;
}
}
Ok(())
}
}
/// State used in server side rendering. This utilizes a pool of [`dioxus_ssr::Renderer`]s to cache static templates between renders.
#[derive(Clone)]
pub struct SSRState {
// We keep a pool of renderers to avoid re-creating them on every request. They are boxed to make them very cheap to move
renderers: Arc<object_pool::Pool<Renderer>>,
}
impl Default for SSRState {
fn default() -> Self {
Self {
renderers: Arc::new(object_pool::Pool::new(10, pre_renderer)),
}
}
renderers: Arc<SsrRendererPool>,
}
impl SSRState {
/// Render the application to HTML.
pub fn render<P: 'static + Clone + serde::Serialize>(&self, cfg: &ServeConfig<P>) -> String {
let ServeConfig { app, props, .. } = cfg;
pub(crate) fn new<P: Clone>(cfg: &ServeConfig<P>) -> Self {
if cfg.incremental.is_some() {
return Self {
renderers: Arc::new(SsrRendererPool::Incremental(object_pool::Pool::new(
10,
|| incremental_pre_renderer(cfg),
))),
};
}
let mut vdom = VirtualDom::new_with_props(*app, props.clone());
let _ = vdom.rebuild();
self.render_vdom(&vdom, cfg)
Self {
renderers: Arc::new(SsrRendererPool::Renderer(object_pool::Pool::new(
10,
pre_renderer,
))),
}
}
/// Render a VirtualDom to HTML.
pub fn render_vdom<P: 'static + Clone + serde::Serialize>(
/// Render the application to HTML.
pub fn render<P: 'static + Clone + serde::Serialize>(
&self,
vdom: &VirtualDom,
route: String,
cfg: &ServeConfig<P>,
) -> String {
let ServeConfig { index, .. } = cfg;
modify_vdom: impl FnOnce(&mut VirtualDom),
) -> Result<String, dioxus_ssr::incremental::IncrementalRendererError> {
let ServeConfig { app, props, .. } = cfg;
let mut renderer = self.renderers.pull(pre_renderer);
let ServeConfig { index, .. } = cfg;
let mut html = String::new();
html += &index.pre_main;
let _ = renderer.render_to(&mut html, vdom);
self.renderers
.render_to(cfg, route, *app, props.clone(), &mut html, modify_vdom)?;
// serialize the props
let _ = crate::props_html::serialize_props::encode_in_element(&cfg.props, &mut html);
@@ -89,12 +129,22 @@ impl SSRState {
html += &index.post_main;
html
Ok(html)
}
}
fn pre_renderer() -> Renderer {
let mut renderer = Renderer::default();
renderer.pre_render = true;
renderer.into()
}
fn incremental_pre_renderer<P: Clone>(
cfg: &ServeConfig<P>,
) -> dioxus_ssr::incremental::IncrementalRenderer<crate::serve_config::EmptyIncrementalRenderTemplate>
{
let builder: &IncrementalRendererConfig<_> = &*cfg.incremental.as_ref().unwrap();
let mut renderer = builder.clone().build();
renderer.renderer_mut().pre_render = true;
renderer
}