Rationalize features and set up defaults so that a) users don't need to specify csr mode by default and b) tests pass without feature flags

This commit is contained in:
Greg Johnston 2022-10-18 10:42:55 -04:00
parent 70b2b3b283
commit 1bbbdbf29e
27 changed files with 119 additions and 128 deletions

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../leptos", default-features = false, features = ["csr"] }
leptos = { path = "../../leptos" }
console_log = "0.2"
log = "0.4"

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../leptos", default-features = false, features = ["stable", "csr"] }
leptos = { path = "../../leptos", features = ["stable"] }
log = "0.4"
console_log = "0.2"

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../leptos", features = ["csr"] }
leptos = { path = "../../leptos" }
log = "0.4"
console_log = "0.2"

View file

@ -5,7 +5,7 @@ edition = "2021"
[dependencies]
anyhow = "1.0.58"
leptos = { path = "../../leptos", features = ["csr"] }
leptos = { path = "../../leptos" }
reqwasm = "0.5.0"
serde = { version = "1", features = ["derive"] }
log = "0.4"

View file

@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
anyhow = "1"
console_log = "0.2"
leptos = { path = "../../../leptos" }
leptos = { path = "../../../leptos", default-features = false }
leptos_meta = { path = "../../../meta", default-features = false }
leptos_router = { path = "../../../router", default-features = false }
log = "0.4"

View file

@ -6,8 +6,8 @@ edition = "2021"
[dependencies]
console_log = "0.2"
log = "0.4"
leptos = { path = "../../leptos", features = ["csr"] }
leptos_router = { path = "../../router", features = ["csr"], version = "0.0" }
leptos = { path = "../../leptos" }
leptos_router = { path = "../../router" }
serde = { version = "1", features = ["derive"] }
futures = "0.3"

View file

@ -8,7 +8,7 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
console_log = "0.2"
leptos = { path = "../../../leptos", features = ["hydrate"] }
leptos = { path = "../../../leptos", default-features = false, features = ["hydrate"] }
todomvc = { path = "../../todomvc", default-features = false, features = ["hydrate"] }
log = "0.4"
wasm-bindgen = "0.2"

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../leptos" }
leptos = { path = "../../leptos", default-features = false }
miniserde = "0.1"
log = "0.4"
console_log = "0.2"

View file

@ -15,9 +15,8 @@ leptos_macro = { path = "../leptos_macro", default-features = false, version = "
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.0.8" }
[features]
default = ["resource"]
default = ["csr"]
csr = ["leptos_core/csr", "leptos_dom/csr", "leptos_macro/csr", "leptos_reactive/csr"]
hydrate = ["leptos_core/hydrate", "leptos_dom/hydrate", "leptos_macro/hydrate", "leptos_reactive/hydrate"]
ssr = ["leptos_core/ssr", "leptos_dom/ssr", "leptos_macro/ssr", "leptos_reactive/ssr"]
resource = ["leptos_reactive/resource"]
stable = ["leptos_dom/stable", "leptos_reactive/stable"]

View file

@ -54,8 +54,6 @@
//! - `csr` Client-side rendering: Generate DOM nodes in the browser
//! - `ssr` Server-side rendering: Generate an HTML string (typically on the server)
//! - `hydrate` Hydration: use this to add interactivity to an SSRed Leptos app
//! - `resource` *(default)* Allows the use of [create_resource] and [Resource]s. Enabled by default,
//! but theres a small benefit in binary size when you disable it if you dont need them.
//! - `stable` By default, Leptos requires `nightly` Rust, which is what allows the ergonomics
//! of calling signals as functions. If you need to use `stable`, you will need to call `.get()`
//! and `.set()` manually.
@ -90,8 +88,10 @@
//! </div>
//! }
//! }
//! ```
//!
//! // Easy to use with Trunk (trunkrs.dev) or with a simple wasm-bindgen setup
//! Leptos is easy to use with [Trunk](https://trunkrs.dev/) (or with a simple wasm-bindgen setup):
//! ```ignore
//! pub fn main() {
//! mount_to_body(|cx| view! { cx, <SimpleCounter initial_value=3 /> })
//! }

View file

@ -8,9 +8,9 @@ repository = "https://github.com/gbj/leptos"
description = "Core functionality for the Leptos web framework."
[dependencies]
leptos_dom = { path = "../leptos_dom", version = "0.0.8" }
leptos_macro = { path = "../leptos_macro", version = "0.0.7" }
leptos_reactive = { path = "../leptos_reactive", version = "0.0.8" }
leptos_dom = { path = "../leptos_dom", default-features = false, version = "0.0.8" }
leptos_macro = { path = "../leptos_macro", default-features = false, version = "0.0.7" }
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.0.8" }
log = "0.4"
[features]

View file

@ -22,8 +22,7 @@ where
pub children: Box<dyn Fn() -> Vec<G>>,
}
/// Iterates over children and displays them, keyed by `PartialEq`. If you want to provide your
/// own key function, use [Index] instead.
/// Iterates over children and displays them, keyed by `PartialEq`.
///
/// This is much more efficient than naively iterating over nodes with `.iter().map(|n| view! { cx, ... })...`,
/// as it avoids re-creating DOM nodes that are not being changed.

View file

@ -42,7 +42,7 @@ where
compile_error!("<Suspense/> can only be used when one of the following features is set on the `leptos` package: 'csr', 'ssr', or 'hydrate'");
}
#[cfg(any(feature = "csr", feature = "hydrate"))]
#[cfg(not(feature = "ssr"))]
fn render_suspense<'a, F, E, G>(
cx: Scope,
context: SuspenseContext,

View file

@ -11,7 +11,7 @@ description = "DOM operations for the Leptos web framework."
futures = { version = "0.3", optional = true }
html-escape = { version = "0.2", optional = true }
js-sys = "0.3"
leptos_reactive = { path = "../leptos_reactive", version = "0.0.8" }
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.0.8" }
serde_json = { version = "1", optional = true }
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4.31"

View file

@ -4,7 +4,7 @@ use leptos_reactive::Scope;
#[cfg(feature = "stable")]
use leptos_reactive::{Memo, ReadSignal, RwSignal};
#[cfg(any(feature = "csr", feature = "hydrate"))]
#[cfg(not(feature = "ssr"))]
use wasm_bindgen::JsCast;
use crate::Node;
@ -83,21 +83,21 @@ impl IntoChild for String {
}
}
#[cfg(any(feature = "csr", feature = "hydrate"))]
#[cfg(not(feature = "ssr"))]
impl IntoChild for web_sys::Node {
fn into_child(self, _cx: Scope) -> Child {
Child::Node(self)
}
}
#[cfg(any(feature = "csr", feature = "hydrate"))]
#[cfg(not(feature = "ssr"))]
impl IntoChild for web_sys::Text {
fn into_child(self, _cx: Scope) -> Child {
Child::Node(self.unchecked_into())
}
}
#[cfg(any(feature = "csr", feature = "hydrate"))]
#[cfg(not(feature = "ssr"))]
impl IntoChild for web_sys::Element {
fn into_child(self, _cx: Scope) -> Child {
Child::Node(self.unchecked_into())
@ -122,7 +122,7 @@ impl IntoChild for Vec<Node> {
}
}
#[cfg(any(feature = "csr", feature = "hydrate"))]
#[cfg(not(feature = "ssr"))]
impl IntoChild for Vec<web_sys::Element> {
fn into_child(self, _cx: Scope) -> Child {
Child::Nodes(

View file

@ -3,11 +3,13 @@ pub mod child;
pub mod class;
pub mod event_delegation;
pub mod logging;
#[cfg(not(feature = "ssr"))]
pub mod mount;
pub mod operations;
pub mod property;
#[cfg(any(feature = "csr", feature = "hydrate"))]
#[cfg(not(feature = "ssr"))]
pub mod reconcile;
#[cfg(any(feature = "csr", feature = "hydrate"))]
#[cfg(not(feature = "ssr"))]
pub mod render;
#[cfg(feature = "ssr")]
pub mod render_to_string;
@ -16,9 +18,11 @@ pub use attribute::*;
pub use child::*;
pub use class::*;
pub use logging::*;
#[cfg(not(feature = "ssr"))]
pub use mount::*;
pub use operations::*;
pub use property::*;
#[cfg(any(feature = "csr", feature = "hydrate"))]
#[cfg(not(feature = "ssr"))]
pub use render::*;
#[cfg(feature = "ssr")]
pub use render_to_string::*;
@ -27,83 +31,19 @@ pub use js_sys;
pub use wasm_bindgen;
pub use web_sys;
#[cfg(any(feature = "csr", feature = "hydrate"))]
#[cfg(not(feature = "ssr"))]
pub type Element = web_sys::Element;
#[cfg(feature = "ssr")]
pub type Element = String;
#[cfg(not(any(feature = "csr", feature = "hydrate", feature = "ssr")))]
pub type Element = web_sys::Element;
#[cfg(any(feature = "csr", feature = "hydrate"))]
#[cfg(not(feature = "ssr"))]
pub type Node = web_sys::Node;
#[cfg(feature = "ssr")]
pub type Node = String;
#[cfg(not(any(feature = "csr", feature = "hydrate", feature = "ssr")))]
pub type Node = web_sys::Node;
use leptos_reactive::Scope;
pub use wasm_bindgen::UnwrapThrowExt;
#[cfg(any(feature = "csr", feature = "hydrate"))]
pub trait Mountable {
fn mount(&self, parent: &web_sys::Element);
}
#[cfg(any(feature = "csr", feature = "hydrate"))]
impl Mountable for Element {
fn mount(&self, parent: &web_sys::Element) {
parent.append_child(self).unwrap_throw();
}
}
#[cfg(any(feature = "csr", feature = "hydrate"))]
impl Mountable for Vec<Element> {
fn mount(&self, parent: &web_sys::Element) {
for element in self {
parent.append_child(element).unwrap_throw();
}
}
}
#[cfg(any(feature = "csr", feature = "hydrate"))]
pub fn mount_to_body<T, F>(f: F)
where
F: Fn(Scope) -> T + 'static,
T: Mountable,
{
mount(document().body().unwrap_throw(), f)
}
#[cfg(any(feature = "csr", feature = "hydrate"))]
pub fn mount<T, F>(parent: web_sys::HtmlElement, f: F)
where
F: Fn(Scope) -> T + 'static,
T: Mountable,
{
use leptos_reactive::create_scope;
// running "mount" intentionally leaks the memory,
// as the "mount" has no parent that can clean it up
let _ = create_scope(move |cx| {
(f(cx)).mount(&parent);
});
}
#[cfg(feature = "hydrate")]
pub fn hydrate<T, F>(parent: web_sys::HtmlElement, f: F)
where
F: Fn(Scope) -> T + 'static,
T: Mountable,
{
// running "hydrate" intentionally leaks the memory,
// as the "hydrate" has no parent that can clean it up
let _ = leptos_reactive::create_scope(move |cx| {
cx.start_hydration(&parent);
(f(cx));
cx.end_hydration();
});
}
#[cfg(feature = "csr")]
pub fn create_component<F, T>(cx: Scope, f: F) -> T
where

58
leptos_dom/src/mount.rs Normal file
View file

@ -0,0 +1,58 @@
use crate::{document, Element};
use leptos_reactive::Scope;
use wasm_bindgen::UnwrapThrowExt;
pub trait Mountable {
fn mount(&self, parent: &web_sys::Element);
}
impl Mountable for Element {
fn mount(&self, parent: &web_sys::Element) {
parent.append_child(self).unwrap_throw();
}
}
impl Mountable for Vec<Element> {
fn mount(&self, parent: &web_sys::Element) {
for element in self {
parent.append_child(element).unwrap_throw();
}
}
}
pub fn mount_to_body<T, F>(f: F)
where
F: Fn(Scope) -> T + 'static,
T: Mountable,
{
mount(document().body().unwrap_throw(), f)
}
pub fn mount<T, F>(parent: web_sys::HtmlElement, f: F)
where
F: Fn(Scope) -> T + 'static,
T: Mountable,
{
use leptos_reactive::create_scope;
// running "mount" intentionally leaks the memory,
// as the "mount" has no parent that can clean it up
let _ = create_scope(move |cx| {
(f(cx)).mount(&parent);
});
}
#[cfg(feature = "hydrate")]
pub fn hydrate<T, F>(parent: web_sys::HtmlElement, f: F)
where
F: Fn(Scope) -> T + 'static,
T: Mountable,
{
// running "hydrate" intentionally leaks the memory,
// as the "hydrate" has no parent that can clean it up
let _ = leptos_reactive::create_scope(move |cx| {
cx.start_hydration(&parent);
(f(cx));
cx.end_hydration();
});
}

View file

@ -25,6 +25,7 @@ leptos_reactive = { path = "../leptos_reactive" }
log = "0.4"
[features]
csr = []
hydrate = []
ssr = []
default = ["ssr"]
csr = ["leptos_core/csr", "leptos_dom/csr", "leptos_reactive/csr"]
hydrate = ["leptos_core/hydrate", "leptos_dom/hydrate", "leptos_reactive/hydrate"]
ssr = ["leptos_core/ssr", "leptos_dom/ssr", "leptos_reactive/ssr"]

View file

@ -6,13 +6,13 @@ fn simple_ssr_test() {
use leptos_reactive::{create_scope, create_signal};
_ = create_scope(|cx| {
let (value, _set_value) = create_signal(cx, 0);
let (value, set_value) = create_signal(cx, 0);
let rendered = view! {
cx,
<div>
<button on:click=move |_| set_value(|value| *value -= 1)>"-1"</button>
<button on:click=move |_| set_value.update(|value| *value -= 1)>"-1"</button>
<span>"Value: " {move || value().to_string()} "!"</span>
<button on:click=move |_| set_value(|value| *value += 1)>"+1"</button>
<button on:click=move |_| set_value.update(|value| *value += 1)>"+1"</button>
</div>
};
@ -34,13 +34,13 @@ fn ssr_test_with_components() {
#[component]
fn Counter(cx: Scope, initial_value: i32) -> Element {
let (value, _set_value) = create_signal(cx, initial_value);
let (value, set_value) = create_signal(cx, initial_value);
view! {
cx,
<div>
<button on:click=move |_| set_value(|value| *value -= 1)>"-1"</button>
<button on:click=move |_| set_value.update(|value| *value -= 1)>"-1"</button>
<span>"Value: " {move || value().to_string()} "!"</span>
<button on:click=move |_| set_value(|value| *value += 1)>"+1"</button>
<button on:click=move |_| set_value.update(|value| *value += 1)>"+1"</button>
</div>
}
}
@ -56,7 +56,7 @@ fn ssr_test_with_components() {
assert_eq!(
rendered,
"<div data-hk=\"0-0\" class=\"counters\"><!--#--><div data-hk=\"0-2-0\"><button>-1</button><span>Value: <!--#-->0<!--/-->!</span><button>+1</button></div><!--/--><!--#--><div data-hk=\"0-3-0\"><button>-1</button><span>Value: <!--#-->0<!--/-->!</span><button>+1</button></div><!--/--></div>"
"<div data-hk=\"0-0\" class=\"counters\"><!--#--><div data-hk=\"0-2-0\"><button>-1</button><span>Value: <!--#-->1<!--/-->!</span><button>+1</button></div><!--/--><!--#--><div data-hk=\"0-3-0\"><button>-1</button><span>Value: <!--#-->2<!--/-->!</span><button>+1</button></div><!--/--></div>"
);
});
}
@ -69,7 +69,7 @@ fn test_classes() {
use leptos_reactive::{create_scope, create_signal};
_ = create_scope(|cx| {
let (value, _set_value) = create_signal(cx, 5);
let (value, set_value) = create_signal(cx, 5);
let rendered = view! {
cx,
<div class="my big" class:a={move || value() > 10} class:red=true class:car={move || value() > 1}></div>

View file

@ -28,7 +28,6 @@ sycamore = "0.8.0-beta.7"
tokio-test = "0.4"
[features]
default = ["resource"]
csr = ["dep:wasm-bindgen", "dep:wasm-bindgen-futures", "dep:web-sys"]
hydrate = [
"dep:base64",
@ -40,5 +39,4 @@ hydrate = [
"dep:web-sys",
]
ssr = ["dep:base64", "dep:serde_json", "dep:tokio"]
resource = []
stable = []

View file

@ -68,7 +68,6 @@ mod effect;
mod hydration;
mod memo;
#[cfg(feature = "resource")]
mod resource;
mod runtime;
mod scope;
@ -81,7 +80,6 @@ pub use context::*;
pub use effect::*;
pub use memo::*;
#[cfg(feature = "resource")]
pub use resource::*;
use runtime::*;
pub use scope::*;
@ -116,7 +114,7 @@ mod tests {
#[bench]
fn create_and_update_1000_signals(b: &mut Bencher) {
use crate::{create_effect, create_memo, create_scope, create_signal};
use crate::{create_isomorphic_effect, create_memo, create_scope, create_signal};
b.iter(|| {
create_scope(|cx| {
@ -126,7 +124,7 @@ mod tests {
let writes = sigs.iter().map(|(_, w)| *w).collect::<Vec<_>>();
let memo = create_memo(cx, move |_| reads.iter().map(|r| r.get()).sum::<i32>());
assert_eq!(memo(), 499500);
create_effect(cx, {
create_isomorphic_effect(cx, {
let acc = Rc::clone(&acc);
move |_| {
acc.set(memo());
@ -147,7 +145,7 @@ mod tests {
#[bench]
fn create_and_dispose_1000_scopes(b: &mut Bencher) {
use crate::{create_effect, create_scope, create_signal};
use crate::{create_isomorphic_effect, create_scope, create_signal};
b.iter(|| {
let acc = Rc::new(Cell::new(0));
@ -157,7 +155,7 @@ mod tests {
let acc = Rc::clone(&acc);
move |cx| {
let (r, w) = create_signal(cx, 0);
create_effect(cx, {
create_isomorphic_effect(cx, {
move |_| {
acc.set(r());
}

View file

@ -29,7 +29,6 @@ pub(crate) struct Runtime {
pub signal_subscribers: RefCell<SecondaryMap<SignalId, RefCell<HashSet<EffectId>>>>,
pub effects: RefCell<SlotMap<EffectId, Rc<RefCell<dyn AnyEffect>>>>,
pub effect_sources: RefCell<SecondaryMap<EffectId, RefCell<HashSet<SignalId>>>>,
#[cfg(feature = "resource")]
pub resources: RefCell<SlotMap<ResourceId, Rc<dyn AnyResource>>>,
}
@ -149,7 +148,6 @@ impl Runtime {
Memo(read)
}
#[cfg(feature = "resource")]
pub(crate) fn create_resource<S, T>(&self, state: Rc<ResourceState<S, T>>) -> ResourceId
where
S: Debug + Clone + 'static,
@ -185,7 +183,6 @@ impl Runtime {
}
}
#[cfg(feature = "resource")]
pub(crate) fn resource<S, T, U>(
&self,
id: ResourceId,
@ -213,7 +210,6 @@ impl Runtime {
}
/// Returns IDs for all [Resource]s found on any scope.
#[cfg(feature = "resource")]
pub(crate) fn all_resources(&self) -> Vec<ResourceId> {
self.resources
.borrow()
@ -222,7 +218,7 @@ impl Runtime {
.collect()
}
#[cfg(all(feature = "ssr", feature = "resource"))]
#[cfg(all(feature = "ssr"))]
pub(crate) fn serialization_resolvers(
&self,
) -> futures::stream::futures_unordered::FuturesUnordered<

View file

@ -1,6 +1,6 @@
use std::{cell::RefCell, collections::HashMap, fmt::Debug, hash::Hash, rc::Rc};
use crate::{create_effect, create_signal, ReadSignal, Scope, WriteSignal};
use crate::{create_isomorphic_effect, create_signal, ReadSignal, Scope, WriteSignal};
/// Creates a conditional signal that only notifies subscribers when a change
/// in the source signals value changes whether it is equal to the key value
@ -67,7 +67,7 @@ where
Rc::new(RefCell::new(HashMap::new()));
let v = Rc::new(RefCell::new(None));
create_effect(cx, {
create_isomorphic_effect(cx, {
let subs = Rc::clone(&subs);
let f = f.clone();
let v = Rc::clone(&v);

View file

@ -337,7 +337,7 @@ where
/// Creates a reactive signal with the getter and setter unified in one value.
/// You may prefer this style, or it may be easier to pass around in a context
/// or as a function argument.
/// /// ```
/// ```
/// # use leptos_reactive::*;
/// # create_scope(|cx| {
/// let count = create_rw_signal(cx, 0);

View file

@ -1,5 +1,5 @@
#[cfg(not(feature = "stable"))]
use leptos_reactive::{create_effect, create_memo, create_scope, create_signal};
use leptos_reactive::{create_isomorphic_effect, create_memo, create_scope, create_signal};
#[cfg(not(feature = "stable"))]
#[test]
@ -13,7 +13,7 @@ fn effect_runs() {
// simulate an arbitrary side effect
let b = Rc::new(RefCell::new(String::new()));
create_effect(cx, {
create_isomorphic_effect(cx, {
let b = b.clone();
move |_| {
let formatted = format!("Value is {}", a());
@ -43,7 +43,7 @@ fn effect_tracks_memo() {
// simulate an arbitrary side effect
let c = Rc::new(RefCell::new(String::new()));
create_effect(cx, {
create_isomorphic_effect(cx, {
let c = c.clone();
move |_| {
*c.borrow_mut() = b();
@ -73,7 +73,7 @@ fn untrack_mutes_effect() {
// simulate an arbitrary side effect
let b = Rc::new(RefCell::new(String::new()));
create_effect(cx, {
create_isomorphic_effect(cx, {
let b = b.clone();
move |_| {
let formatted = format!("Value is {}", cx.untrack(a));

View file

@ -8,7 +8,7 @@ repository = "https://github.com/gbj/leptos"
description = "Tools to set HTML metadata in the Leptos web framework."
[dependencies]
leptos = { path = "../leptos", version = "0.0" }
leptos = { path = "../leptos", version = "0.0", default-features = false }
log = "0.4"
[dependencies.web-sys]
@ -19,6 +19,7 @@ features = [
]
[features]
default = ["csr"]
csr = ["leptos/csr"]
hydrate = ["leptos/hydrate"]
ssr = ["leptos/ssr"]

View file

@ -8,7 +8,7 @@ repository = "https://github.com/gbj/leptos"
description = "Router for the Leptos web framework."
[dependencies]
leptos = { path = "../leptos", version = "0.0" }
leptos = { path = "../leptos", version = "0.0", default-features = false }
common_macros = "0.1"
itertools = "0.10"
lazy_static = "1"
@ -52,6 +52,7 @@ features = [
]
[features]
default = ["csr"]
csr = ["leptos/csr", "dep:js-sys", "dep:wasm-bindgen"]
hydrate = [
"leptos/hydrate",