perf: exclude hydration code in CSR mode (#1372)

This commit is contained in:
Greg Johnston 2023-07-17 12:20:33 -04:00 committed by GitHub
parent 4d4d15436b
commit 47148f2033
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 18 deletions

View File

@ -28,13 +28,13 @@ leptos = { path = "." }
default = ["serde"]
template_macro = ["leptos_dom/web", "web-sys", "wasm-bindgen"]
csr = [
"leptos_dom/web",
"leptos_dom/csr",
"leptos_macro/csr",
"leptos_reactive/csr",
"leptos_server/csr",
]
hydrate = [
"leptos_dom/web",
"leptos_dom/hydrate",
"leptos_macro/hydrate",
"leptos_reactive/hydrate",
"leptos_server/hydrate",

View File

@ -164,7 +164,9 @@ features = [
[features]
default = []
web = ["leptos_reactive/csr"]
web = []
csr = ["leptos_reactive/csr", "web"]
hydrate = ["leptos_reactive/hydrate", "web"]
ssr = ["leptos_reactive/ssr"]
nightly = ["leptos_reactive/nightly"]
nonce = ["dep:base64", "dep:getrandom", "dep:rand"]

View File

@ -1,17 +1,16 @@
use cfg_if::cfg_if;
use std::{cell::RefCell, fmt::Display};
cfg_if! {
if #[cfg(all(target_arch = "wasm32", feature = "web"))] {
#[cfg(all(target_arch = "wasm32", feature = "hydrate"))]
mod hydration {
use once_cell::unsync::Lazy as LazyCell;
use std::collections::HashMap;
use std::{cell::RefCell, collections::HashMap};
use wasm_bindgen::JsCast;
// We can tell if we start in hydration mode by checking to see if the
// id "_0-1" is present in the DOM. If it is, we know we are hydrating from
// the server, if not, we are starting off in CSR
thread_local! {
static HYDRATION_COMMENTS: LazyCell<HashMap<String, web_sys::Comment>> = LazyCell::new(|| {
pub static HYDRATION_COMMENTS: LazyCell<HashMap<String, web_sys::Comment>> = LazyCell::new(|| {
let document = crate::document();
let body = document.body().unwrap();
let walker = document
@ -31,7 +30,7 @@ cfg_if! {
});
#[cfg(debug_assertions)]
pub(crate) static VIEW_MARKERS: LazyCell<HashMap<String, web_sys::Comment>> = LazyCell::new(|| {
pub static VIEW_MARKERS: LazyCell<HashMap<String, web_sys::Comment>> = LazyCell::new(|| {
let document = crate::document();
let body = document.body().unwrap();
let walker = document
@ -48,7 +47,7 @@ cfg_if! {
map
});
static IS_HYDRATING: RefCell<LazyCell<bool>> = RefCell::new(LazyCell::new(|| {
pub static IS_HYDRATING: RefCell<LazyCell<bool>> = RefCell::new(LazyCell::new(|| {
#[cfg(debug_assertions)]
return crate::document().get_element_by_id("_0-1").is_some()
|| crate::document().get_element_by_id("_0-1o").is_some()
@ -60,12 +59,14 @@ cfg_if! {
}));
}
pub(crate) fn get_marker(id: &str) -> Option<web_sys::Comment> {
HYDRATION_COMMENTS.with(|comments| comments.get(id).cloned())
pub fn get_marker(id: &str) -> Option<web_sys::Comment> {
HYDRATION_COMMENTS.with(|comments| comments.get(id).cloned())
}
}
}
#[cfg(all(target_arch = "wasm32", feature = "hydrate"))]
pub(crate) use hydration::*;
/// A stable identifier within the server-rendering or hydration process.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Default)]
pub struct HydrationKey {
@ -125,23 +126,27 @@ impl HydrationCtx {
#[cfg(all(target_arch = "wasm32", feature = "web"))]
pub(crate) fn stop_hydrating() {
IS_HYDRATING.with(|is_hydrating| {
std::mem::take(&mut *is_hydrating.borrow_mut());
})
#[cfg(feature = "hydrate")]
{
IS_HYDRATING.with(|is_hydrating| {
std::mem::take(&mut *is_hydrating.borrow_mut());
})
}
}
/// Whether the UI is currently in the process of hydrating from the server-sent HTML.
pub fn is_hydrating() -> bool {
#[cfg(all(target_arch = "wasm32", feature = "web"))]
#[cfg(all(target_arch = "wasm32", feature = "hydrate"))]
{
IS_HYDRATING.with(|is_hydrating| **is_hydrating.borrow())
}
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
#[cfg(not(all(target_arch = "wasm32", feature = "hydrate")))]
{
false
}
}
#[allow(dead_code)] // not used in CSR
pub(crate) fn to_string(id: &HydrationKey, closing: bool) -> String {
#[cfg(debug_assertions)]
return format!("_{id}{}", if closing { 'c' } else { 'o' });

View File

@ -416,11 +416,18 @@ impl Comment {
Self { content }
} else {
#[cfg(not(feature = "hydrate"))]
{
_ = id;
_ = closing;
}
let node = COMMENT.with(|comment| comment.clone_node().unwrap());
#[cfg(debug_assertions)]
node.set_text_content(Some(&format!(" {content} ")));
#[cfg(feature = "hydrate")]
if HydrationCtx::is_hydrating() {
let id = HydrationCtx::to_string(id, closing);