router/fullstack/ssr intigration
This commit is contained in:
1 parent
495fd22bfd
commit
1704ee0068
21 files changed
+507
-203
No files matched your search
@@ -30,13 +30,13 @@ salvo = { version = "0.37.7", optional = true, features = ["serve-static", "ws"]
|
||||
serde = "1.0.159"
|
||||
|
||||
# Dioxus + SSR
|
||||
dioxus-core = { path = "../core", version = "^0.3.0" }
|
||||
dioxus = { path = "../dioxus", version = "^0.3.0" }
|
||||
dioxus-ssr = { path = "../ssr", version = "^0.3.0", optional = true }
|
||||
hyper = { version = "0.14.25", optional = true }
|
||||
http = { version = "0.2.9", optional = true }
|
||||
|
||||
# Router Intigration
|
||||
dioxus-router = { path = "../router", version = "^0.3.0", optional = true }
|
||||
dioxus-router = { path = "../router", version = "^0.3.0", features = ["ssr"], optional = true }
|
||||
|
||||
log = "0.4.17"
|
||||
once_cell = "1.17.1"
|
||||
@@ -59,7 +59,7 @@ dioxus-hot-reload = { path = "../hot-reload" }
|
||||
web-sys = { version = "0.3.61", features = ["Window", "Document", "Element", "HtmlDocument", "Storage", "console"] }
|
||||
|
||||
[features]
|
||||
default = ["hot-reload", "default-tls"]
|
||||
default = ["hot-reload", "default-tls", "router"]
|
||||
router = ["dioxus-router"]
|
||||
hot-reload = ["serde_json", "tokio-stream", "futures-util"]
|
||||
warp = ["dep:warp", "http-body", "ssr"]
|
||||
|
||||
@@ -14,8 +14,8 @@ use serde::{Deserialize, Serialize};
|
||||
fn main() {
|
||||
#[cfg(feature = "web")]
|
||||
dioxus_web::launch_with_props(
|
||||
App,
|
||||
AppProps { route: None },
|
||||
Router,
|
||||
Default::default(),
|
||||
dioxus_web::Config::new().hydrate(true),
|
||||
);
|
||||
#[cfg(feature = "ssr")]
|
||||
@@ -33,11 +33,6 @@ fn main() {
|
||||
true
|
||||
}));
|
||||
|
||||
use axum::extract::State;
|
||||
use std::str::FromStr;
|
||||
|
||||
PostServerData::register().unwrap();
|
||||
GetServerData::register().unwrap();
|
||||
tokio::runtime::Runtime::new()
|
||||
.unwrap()
|
||||
.block_on(async move {
|
||||
@@ -46,28 +41,12 @@ fn main() {
|
||||
axum::Server::bind(&addr)
|
||||
.serve(
|
||||
axum::Router::new()
|
||||
// Serve the dist/assets folder with the javascript and WASM files created by the CLI
|
||||
.serve_static_assets("./dist")
|
||||
// Register server functions
|
||||
.register_server_fns("")
|
||||
// Connect to the hot reload server
|
||||
.connect_hot_reload()
|
||||
// If the path is unknown, render the application
|
||||
.fallback(
|
||||
move |uri: http::uri::Uri, State(ssr_state): State<SSRState>| {
|
||||
let rendered = ssr_state.render(
|
||||
&ServeConfigBuilder::new(
|
||||
App,
|
||||
AppProps {
|
||||
route: Route::from_str(&uri.to_string()).ok(),
|
||||
},
|
||||
)
|
||||
.build(),
|
||||
);
|
||||
async move { axum::body::Full::from(rendered) }
|
||||
},
|
||||
.serve_dioxus_application(
|
||||
"",
|
||||
ServeConfigBuilder::new_with_router(
|
||||
dioxus_fullstack::prelude::FullstackRouterConfig::<Route>::default()).incremental(IncrementalRendererConfig::default())
|
||||
.build(),
|
||||
)
|
||||
.with_state(SSRState::default())
|
||||
.into_make_service(),
|
||||
)
|
||||
.await
|
||||
@@ -87,10 +66,7 @@ enum Route {
|
||||
#[inline_props]
|
||||
fn Blog(cx: Scope) -> Element {
|
||||
render! {
|
||||
Link {
|
||||
target: Route::Home {},
|
||||
"Go to counter"
|
||||
}
|
||||
Link { target: Route::Home {}, "Go to counter" }
|
||||
table {
|
||||
tbody {
|
||||
for _ in 0..100 {
|
||||
@@ -105,38 +81,14 @@ fn Blog(cx: Scope) -> Element {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Props, PartialEq, Serialize, Deserialize)]
|
||||
struct AppProps {
|
||||
route: Option<Route>,
|
||||
}
|
||||
|
||||
fn App(cx: Scope<AppProps>) -> Element {
|
||||
#[cfg(feature = "ssr")]
|
||||
let initial_route = cx.props.route.clone().unwrap_or(Route::Home {});
|
||||
cx.render(rsx! {
|
||||
Router {
|
||||
config: move || RouterConfig::default().history({
|
||||
#[cfg(feature = "ssr")]
|
||||
let history = MemoryHistory::with_initial_path(initial_route);
|
||||
#[cfg(feature = "web")]
|
||||
let history = WebHistory::default();
|
||||
history
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[inline_props]
|
||||
fn Home(cx: Scope) -> Element {
|
||||
let mut count = use_state(cx, || 0);
|
||||
let text = use_state(cx, || "...".to_string());
|
||||
|
||||
cx.render(rsx! {
|
||||
Link {
|
||||
target: Route::Blog {}
|
||||
"Go to blog"
|
||||
}
|
||||
div{
|
||||
Link { target: Route::Blog {}, "Go to blog" }
|
||||
div {
|
||||
h1 { "High-Five counter: {count}" }
|
||||
button { onclick: move |_| count += 1, "Up high!" }
|
||||
button { onclick: move |_| count -= 1, "Down low!" }
|
||||
|
||||
@@ -63,7 +63,6 @@ use axum::{
|
||||
routing::{get, post},
|
||||
Router,
|
||||
};
|
||||
use dioxus_core::VirtualDom;
|
||||
use server_fn::{Encoding, Payload, ServerFunctionRegistry};
|
||||
use std::error::Error;
|
||||
use std::sync::Arc;
|
||||
@@ -311,15 +310,13 @@ where
|
||||
cfg: impl Into<ServeConfig<P>>,
|
||||
) -> Self {
|
||||
let cfg = cfg.into();
|
||||
let ssr_state = SSRState::new(&cfg);
|
||||
|
||||
// Add server functions and render index.html
|
||||
self.serve_static_assets(cfg.assets_path)
|
||||
.route(
|
||||
"/",
|
||||
get(render_handler).with_state((cfg, SSRState::default())),
|
||||
)
|
||||
.connect_hot_reload()
|
||||
.register_server_fns(server_fn_route)
|
||||
.fallback(get(render_handler).with_state((cfg, ssr_state)))
|
||||
}
|
||||
|
||||
fn connect_hot_reload(self) -> Self {
|
||||
@@ -358,13 +355,18 @@ async fn render_handler<P: Clone + serde::Serialize + Send + Sync + 'static>(
|
||||
) -> impl IntoResponse {
|
||||
let (parts, _) = request.into_parts();
|
||||
let parts: Arc<RequestParts> = Arc::new(parts.into());
|
||||
let url = parts.uri.path_and_query().unwrap().to_string();
|
||||
let server_context = DioxusServerContext::new(parts);
|
||||
let mut vdom =
|
||||
VirtualDom::new_with_props(cfg.app, cfg.props.clone()).with_root_context(server_context);
|
||||
let _ = vdom.rebuild();
|
||||
|
||||
let rendered = ssr_state.render_vdom(&vdom, &cfg);
|
||||
Full::from(rendered)
|
||||
match ssr_state.render(url, &cfg, |vdom| {
|
||||
vdom.base_scope().provide_context(server_context);
|
||||
}) {
|
||||
Ok(html) => Full::from(html).into_response(),
|
||||
Err(e) => {
|
||||
log::error!("Failed to render page: {}", e);
|
||||
report_err(e).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A default handler for server functions. It will deserialize the request, call the server function, and serialize the response.
|
||||
|
||||
@@ -282,7 +282,7 @@ impl DioxusRouterExt for Router {
|
||||
self.serve_static_assets(cfg.assets_path)
|
||||
.connect_hot_reload()
|
||||
.register_server_fns(server_fn_path)
|
||||
.push(Router::with_path("/").get(SSRHandler { cfg }))
|
||||
.push(Router::with_path("/<**any_path>").get(SSRHandler { cfg }))
|
||||
}
|
||||
|
||||
fn connect_hot_reload(self) -> Self {
|
||||
|
||||
@@ -169,8 +169,8 @@ pub fn serve_dioxus_application<P: Clone + serde::Serialize + Send + Sync + 'sta
|
||||
|
||||
connect_hot_reload()
|
||||
.or(register_server_fns(server_fn_route))
|
||||
.or(warp::path::end().and(render_ssr(cfg)))
|
||||
.or(serve_dir)
|
||||
.or(render_ssr(cfg))
|
||||
.boxed()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use dioxus_core::Template;
|
||||
use dioxus::prelude::Template;
|
||||
use tokio::sync::{
|
||||
watch::{channel, Receiver},
|
||||
RwLock,
|
||||
@@ -9,7 +9,8 @@ use tokio::sync::{
|
||||
#[derive(Clone)]
|
||||
pub struct HotReloadState {
|
||||
// The cache of all templates that have been modified since the last time we checked
|
||||
pub(crate) templates: Arc<RwLock<std::collections::HashSet<dioxus_core::Template<'static>>>>,
|
||||
pub(crate) templates:
|
||||
Arc<RwLock<std::collections::HashSet<dioxus::prelude::Template<'static>>>>,
|
||||
// The channel to send messages to the hot reload thread
|
||||
pub(crate) message_receiver: Receiver<Option<Template<'static>>>,
|
||||
}
|
||||
|
||||
Whitespace-only changes.
@@ -10,8 +10,6 @@ mod props_html;
|
||||
mod adapters;
|
||||
#[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
|
||||
mod hot_reload;
|
||||
#[cfg(feature = "router")]
|
||||
mod incremental;
|
||||
#[cfg(feature = "ssr")]
|
||||
mod render;
|
||||
#[cfg(feature = "ssr")]
|
||||
@@ -31,6 +29,8 @@ pub mod prelude {
|
||||
pub use crate::props_html::deserialize_props::get_root_props_from_document;
|
||||
#[cfg(feature = "ssr")]
|
||||
pub use crate::render::SSRState;
|
||||
#[cfg(all(feature = "router", feature = "ssr"))]
|
||||
pub use crate::serve_config::FullstackRouterConfig;
|
||||
#[cfg(feature = "ssr")]
|
||||
pub use crate::serve_config::{ServeConfig, ServeConfigBuilder};
|
||||
#[cfg(feature = "ssr")]
|
||||
@@ -40,5 +40,7 @@ pub mod prelude {
|
||||
#[cfg(feature = "ssr")]
|
||||
pub use crate::server_fn::{ServerFnTraitObj, ServerFunction};
|
||||
pub use dioxus_server_macro::*;
|
||||
#[cfg(feature = "ssr")]
|
||||
pub use dioxus_ssr::incremental::IncrementalRendererConfig;
|
||||
pub use server_fn::{self, ServerFn as _, ServerFnError};
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
#![allow(non_snake_case)]
|
||||
//! Configeration for how to serve a Dioxus application
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use dioxus_core::Component;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
/// A ServeConfig is used to configure how to serve a Dioxus application. It contains information about how to serve static assets, and what content to render with [`dioxus-ssr`].
|
||||
#[derive(Clone)]
|
||||
@@ -14,6 +15,164 @@ pub struct ServeConfigBuilder<P: Clone> {
|
||||
pub(crate) root_id: Option<&'static str>,
|
||||
pub(crate) index_path: Option<&'static str>,
|
||||
pub(crate) assets_path: Option<&'static str>,
|
||||
#[cfg(feature = "router")]
|
||||
pub(crate) incremental: Option<
|
||||
std::sync::Arc<
|
||||
dioxus_ssr::incremental::IncrementalRendererConfig<EmptyIncrementalRenderTemplate>,
|
||||
>,
|
||||
>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "router")]
|
||||
fn default_external_navigation_handler<R>() -> fn(Scope) -> Element
|
||||
where
|
||||
R: dioxus_router::prelude::Routable,
|
||||
<R as std::str::FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
dioxus_router::prelude::FailureExternalNavigation::<R>
|
||||
}
|
||||
|
||||
#[cfg(feature = "router")]
|
||||
/// The configeration for the router
|
||||
#[derive(Props, serde::Serialize, serde::Deserialize)]
|
||||
pub struct FullstackRouterConfig<R>
|
||||
where
|
||||
R: dioxus_router::prelude::Routable,
|
||||
<R as std::str::FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
#[serde(skip)]
|
||||
#[serde(default = "default_external_navigation_handler::<R>")]
|
||||
failure_external_navigation: fn(Scope) -> Element,
|
||||
scroll_restoration: bool,
|
||||
#[serde(skip)]
|
||||
phantom: std::marker::PhantomData<R>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "router")]
|
||||
impl<R> Clone for FullstackRouterConfig<R>
|
||||
where
|
||||
R: dioxus_router::prelude::Routable,
|
||||
<R as std::str::FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
failure_external_navigation: self.failure_external_navigation,
|
||||
scroll_restoration: self.scroll_restoration,
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "router")]
|
||||
impl<R> Copy for FullstackRouterConfig<R>
|
||||
where
|
||||
R: dioxus_router::prelude::Routable,
|
||||
<R as std::str::FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(feature = "router")]
|
||||
impl<R> Default for FullstackRouterConfig<R>
|
||||
where
|
||||
R: dioxus_router::prelude::Routable,
|
||||
<R as std::str::FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
failure_external_navigation: dioxus_router::prelude::FailureExternalNavigation::<R>,
|
||||
scroll_restoration: true,
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "router")]
|
||||
fn RouteWithCfg<R>(cx: Scope<FullstackRouterConfig<R>>) -> Element
|
||||
where
|
||||
R: dioxus_router::prelude::Routable,
|
||||
<R as std::str::FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
use dioxus_router::prelude::RouterConfig;
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
let context: crate::prelude::DioxusServerContext = cx
|
||||
.consume_context()
|
||||
.expect("RouteWithCfg should be served by dioxus fullstack");
|
||||
|
||||
let cfg = *cx.props;
|
||||
render! {
|
||||
dioxus_router::prelude::GenericRouter::<R> {
|
||||
config: move || {
|
||||
RouterConfig::default()
|
||||
.failure_external_navigation(cfg.failure_external_navigation)
|
||||
.history({
|
||||
#[cfg(feature = "ssr")]
|
||||
let history = dioxus_router::prelude::MemoryHistory::with_initial_path(
|
||||
context
|
||||
.request_parts()
|
||||
.uri
|
||||
.to_string()
|
||||
.parse()
|
||||
.unwrap_or_else(|err| {
|
||||
log::error!("Failed to parse uri: {}", err);
|
||||
"/"
|
||||
.parse()
|
||||
.unwrap_or_else(|err| {
|
||||
panic!("Failed to parse uri: {}", err);
|
||||
})
|
||||
}),
|
||||
);
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
let history = dioxus_router::prelude::WebHistory::new(
|
||||
None,
|
||||
cfg.scroll_restoration,
|
||||
);
|
||||
history
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "router")]
|
||||
/// A template for incremental rendering that does nothing.
|
||||
#[derive(Default, Clone)]
|
||||
pub struct EmptyIncrementalRenderTemplate;
|
||||
|
||||
#[cfg(feature = "router")]
|
||||
impl dioxus_ssr::incremental::RenderHTML for EmptyIncrementalRenderTemplate {
|
||||
fn render_after_body<R: std::io::Write>(
|
||||
&self,
|
||||
_: &mut R,
|
||||
) -> Result<(), dioxus_ssr::incremental::IncrementalRendererError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_before_body<R: std::io::Write>(
|
||||
&self,
|
||||
_: &mut R,
|
||||
) -> Result<(), dioxus_ssr::incremental::IncrementalRendererError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "router")]
|
||||
impl<R> ServeConfigBuilder<FullstackRouterConfig<R>>
|
||||
where
|
||||
R: dioxus_router::prelude::Routable,
|
||||
<R as std::str::FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
/// Create a new ServeConfigBuilder to serve a router on the server.
|
||||
pub fn new_with_router(cfg: FullstackRouterConfig<R>) -> Self {
|
||||
Self {
|
||||
app: RouteWithCfg::<R>,
|
||||
props: cfg,
|
||||
root_id: None,
|
||||
index_path: None,
|
||||
assets_path: None,
|
||||
incremental: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Clone> ServeConfigBuilder<P> {
|
||||
@@ -25,9 +184,21 @@ impl<P: Clone> ServeConfigBuilder<P> {
|
||||
root_id: None,
|
||||
index_path: None,
|
||||
assets_path: None,
|
||||
#[cfg(feature = "router")]
|
||||
incremental: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "router")]
|
||||
/// Enable incremental static generation
|
||||
pub fn incremental(
|
||||
mut self,
|
||||
cfg: dioxus_ssr::incremental::IncrementalRendererConfig<EmptyIncrementalRenderTemplate>,
|
||||
) -> Self {
|
||||
self.incremental = Some(std::sync::Arc::new(cfg));
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the path of the index.html file to be served. (defaults to {assets_path}/index.html)
|
||||
pub fn index_path(mut self, index_path: &'static str) -> Self {
|
||||
self.index_path = Some(index_path);
|
||||
@@ -64,6 +235,8 @@ impl<P: Clone> ServeConfigBuilder<P> {
|
||||
props: self.props,
|
||||
index,
|
||||
assets_path,
|
||||
#[cfg(feature = "router")]
|
||||
incremental: self.incremental,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,6 +279,12 @@ pub struct ServeConfig<P: Clone> {
|
||||
pub(crate) props: P,
|
||||
pub(crate) index: IndexHtml,
|
||||
pub(crate) assets_path: &'static str,
|
||||
#[cfg(feature = "router")]
|
||||
pub(crate) incremental: Option<
|
||||
std::sync::Arc<
|
||||
dioxus_ssr::incremental::IncrementalRendererConfig<EmptyIncrementalRenderTemplate>,
|
||||
>,
|
||||
>,
|
||||
}
|
||||
|
||||
impl<P: Clone> From<ServeConfigBuilder<P>> for ServeConfig<P> {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use dioxus_core::ScopeState;
|
||||
use dioxus::prelude::ScopeState;
|
||||
|
||||
/// A trait for an object that contains a server context
|
||||
pub trait HasServerContext {
|
||||
|
||||
Reference in new issue
Block a user