Fix hydration of suspense fragments that contain text nodes (#3287)

* Fix hydration of suspense fragments that contain text nodes

* fix release builds

* disable link deduplication

* restore meta tag deduplication

* Add a test for the failed hydration case

* make changes to the document trait non-breaking

* remove info log from server future hook

* restore default implementation - this was also a breaking change

* fix semver breakage

* clean up server_future

* Cleanup unused code

* fix clippy

---------

Co-authored-by: Jonathan Kelley <jkelleyrtp@gmail.com>
This commit is contained in:
Evan AlmloffandJonathan Kelley authored and GitHub committed 2025-01-07 19:47:23 -08:00
1 parent 57d637184f
commit d41ab3a756
33 files changed
+644 -222

No files matched your search

+22 -3
View File
@@ -33,6 +33,8 @@ use std::{
sync::{Arc, RwLock},
};
use crate::html_storage::serialize::SerializedHydrationData;
/// Sections are identified by a unique id based on the suspense path. We only track the path of suspense boundaries because the client may render different components than the server.
#[derive(Clone, Debug, Default)]
struct MountPath {
@@ -109,7 +111,7 @@ impl<E> StreamingRenderer<E> {
&self,
id: Mount,
html: impl FnOnce(&mut W) -> std::fmt::Result,
data: impl Display,
resolved_data: SerializedHydrationData,
into: &mut W,
) -> std::fmt::Result {
// Then replace the suspense placeholder with the new content
@@ -119,10 +121,27 @@ impl<E> StreamingRenderer<E> {
html(into)?;
// Restore the old path
*self.current_path.write().unwrap() = old_path;
// dx_hydrate accepts 2-4 arguments. The first two are required, the rest are optional
// The arguments are:
// 1. The id of the nodes we are hydrating under
// 2. The serialized data required to hydrate those components
// 3. (in debug mode) The type names of the serialized data
// 4. (in debug mode) The locations of the serialized data
let raw_data = resolved_data.data;
write!(
into,
r#"</div><script>window.dx_hydrate([{id}], "{data}")</script>"#
)
r#"</div><script>window.dx_hydrate([{id}], "{raw_data}""#
)?;
#[cfg(debug_assertions)]
{
// In debug mode, we also send down the type names and locations of the serialized data
let debug_types = &resolved_data.debug_types;
let debug_locations = &resolved_data.debug_locations;
write!(into, r#", {debug_types}, {debug_locations}"#,)?;
}
write!(into, r#")</script>"#)?;
Ok(())
}
/// Close the stream with an error