From f20c74fa981ab50caf9f000f3704731c46bdd0ed Mon Sep 17 00:00:00 2001 From: Greg Johnston Date: Fri, 23 Dec 2022 14:23:06 -0500 Subject: [PATCH] SSR changes to support integrations --- leptos_dom/src/ssr.rs | 38 +++++++++++++++++++++++++++--------- leptos_reactive/src/scope.rs | 6 ++++-- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/leptos_dom/src/ssr.rs b/leptos_dom/src/ssr.rs index 6a3460a29..d9a02e778 100644 --- a/leptos_dom/src/ssr.rs +++ b/leptos_dom/src/ssr.rs @@ -77,6 +77,30 @@ pub fn render_to_stream_with_prefix( view: impl FnOnce(Scope) -> View + 'static, prefix: impl FnOnce(Scope) -> Cow<'static, str> + 'static, ) -> impl Stream { + let (stream, runtime, _) = render_to_stream_with_prefix_undisposed(view, prefix); + runtime.dispose(); + stream +} + +/// Renders a function to a stream of HTML strings and returns the [Scope] and [Runtime] that were created, so +/// they can be disposed when appropriate. After the `view` runs, the `prefix` will run with +/// the same scope. This can be used to generate additional HTML that has access to the same `Scope`. +/// +/// This renders: +/// 1) the prefix +/// 2) the application shell +/// a) HTML for everything that is not under a ``, +/// b) the `fallback` for any `` component that is not already resolved, and +/// c) JavaScript necessary to receive streaming [Resource](leptos_reactive::Resource) data. +/// 3) streaming [Resource](leptos_reactive::Resource) data. Resources begin loading on the +/// server and are sent down to the browser to resolve. On the browser, if the app sees that +/// it is waiting for a resource to resolve from the server, it doesn't run it initially. +/// 4) HTML fragments to replace each `` fallback with its actual data as the resources +/// read under that `` resolve. +pub fn render_to_stream_with_prefix_undisposed( + view: impl FnOnce(Scope) -> View + 'static, + prefix: impl FnOnce(Scope) -> Cow<'static, str> + 'static +) -> (impl Stream, RuntimeId, ScopeId) { HydrationCtx::reset_id(); // create the runtime @@ -84,8 +108,8 @@ pub fn render_to_stream_with_prefix( let ( (shell, prefix, pending_resources, pending_fragments, serializers), + scope, _, - disposer, ) = run_scope_undisposed(runtime, { move |cx| { // the actual app body/template code @@ -155,7 +179,7 @@ pub fn render_to_stream_with_prefix( }); // HTML for the view function and script to store resources - futures::stream::once(async move { + let stream = futures::stream::once(async move { format!( r#" {prefix} @@ -171,13 +195,9 @@ pub fn render_to_stream_with_prefix( // TODO these should be combined again in a way that chains them appropriately // such that individual resources can resolve before all fragments are done .chain(fragments) - .chain(resources) - // dispose of Scope and Runtime - .chain(futures::stream::once(async move { - disposer.dispose(); - runtime.dispose(); - Default::default() - })) + .chain(resources); + + (stream, runtime, scope) } impl View { diff --git a/leptos_reactive/src/scope.rs b/leptos_reactive/src/scope.rs index 53df0dc3b..30d72e4c4 100644 --- a/leptos_reactive/src/scope.rs +++ b/leptos_reactive/src/scope.rs @@ -70,8 +70,10 @@ pub fn run_scope_undisposed( /// is [Copy] and `'static` this does not add much overhead or lifetime complexity. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct Scope { - pub(crate) runtime: RuntimeId, - pub(crate) id: ScopeId, + #[doc(hidden)] + pub runtime: RuntimeId, + #[doc(hidden)] + pub id: ScopeId, } impl Scope {