mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
Chore: remove old cruft in web crate (#2957)
This commit is contained in:
parent
c7124e41fb
commit
c5f00bf7d4
8 changed files with 0 additions and 303 deletions
|
@ -1,35 +0,0 @@
|
|||
|
||||
// ## RequestAnimationFrame and RequestIdleCallback
|
||||
// ------------------------------------------------
|
||||
// React implements "jank free rendering" by deliberately not blocking the browser's main thread. For large diffs, long
|
||||
// running work, and integration with things like React-Three-Fiber, it's extremely important to avoid blocking the
|
||||
// main thread.
|
||||
//
|
||||
// React solves this problem by breaking up the rendering process into a "diff" phase and a "render" phase. In Dioxus,
|
||||
// the diff phase is non-blocking, using "work_with_deadline" to allow the browser to process other events. When the diff phase
|
||||
// is finally complete, the VirtualDOM will return a set of "Mutations" for this crate to apply.
|
||||
//
|
||||
// Here, we schedule the "diff" phase during the browser's idle period, achieved by calling RequestIdleCallback and then
|
||||
// setting a timeout from the that completes when the idleperiod is over. Then, we call requestAnimationFrame
|
||||
//
|
||||
// From Google's guide on rAF and rIC:
|
||||
// -----------------------------------
|
||||
//
|
||||
// If the callback is fired at the end of the frame, it will be scheduled to go after the current frame has been committed,
|
||||
// which means that style changes will have been applied, and, importantly, layout calculated. If we make DOM changes inside
|
||||
// of the idle callback, those layout calculations will be invalidated. If there are any kind of layout reads in the next
|
||||
// frame, e.g. getBoundingClientRect, clientWidth, etc, the browser will have to perform a Forced Synchronous Layout,
|
||||
// which is a potential performance bottleneck.
|
||||
//
|
||||
// Another reason not trigger DOM changes in the idle callback is that the time impact of changing the DOM is unpredictable,
|
||||
// and as such we could easily go past the deadline the browser provided.
|
||||
//
|
||||
// The best practice is to only make DOM changes inside of a requestAnimationFrame callback, since it is scheduled by the
|
||||
// browser with that type of work in mind. That means that our code will need to use a document fragment, which can then
|
||||
// be appended in the next requestAnimationFrame callback. If you are using a VDOM library, you would use requestIdleCallback
|
||||
// to make changes, but you would apply the DOM patches in the next requestAnimationFrame callback, not the idle callback.
|
||||
//
|
||||
// Essentially:
|
||||
// ------------
|
||||
// - Do the VDOM work during the idlecallback
|
||||
// - Do DOM work in the next requestAnimationFrame callback
|
|
@ -1,10 +0,0 @@
|
|||
Examples
|
||||
========
|
||||
|
||||
# Hydrate
|
||||
|
||||
- `hydrate` show hydrate
|
||||
|
||||
# Async
|
||||
|
||||
- `timeout_count` button to add count and show count in the future
|
|
@ -1,57 +0,0 @@
|
|||
use dioxus::prelude::*;
|
||||
use dioxus_web::Config;
|
||||
use web_sys::window;
|
||||
|
||||
fn app() -> Element {
|
||||
rsx! {
|
||||
div { h1 { "thing 1" } }
|
||||
div { h2 { "thing 2" } }
|
||||
div {
|
||||
h2 { "thing 2" }
|
||||
"asd"
|
||||
"asd"
|
||||
Bapp {}
|
||||
}
|
||||
{(0..10).map(|f| rsx! {
|
||||
div {
|
||||
"thing {f}"
|
||||
}
|
||||
})}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn Bapp() -> Element {
|
||||
rsx! {
|
||||
div { h1 { "thing 1" } }
|
||||
div { h2 { "thing 2" } }
|
||||
div {
|
||||
h2 { "thing 2" }
|
||||
"asd"
|
||||
"asd"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
console_error_panic_hook::set_once();
|
||||
tracing_wasm::set_as_global_default();
|
||||
|
||||
let mut dom = VirtualDom::new(app);
|
||||
dom.rebuild(&mut dioxus_core::NoOpMutations);
|
||||
|
||||
let pre = dioxus_ssr::pre_render(&dom);
|
||||
tracing::trace!("{}", pre);
|
||||
|
||||
// set the inner content of main to the pre-rendered content
|
||||
window()
|
||||
.unwrap()
|
||||
.document()
|
||||
.unwrap()
|
||||
.get_element_by_id("main")
|
||||
.unwrap()
|
||||
.set_inner_html(&pre);
|
||||
|
||||
// now rehydrate
|
||||
dioxus_web::launch::launch(app, vec![], Config::new().hydrate(true));
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// https://jakelazaroff.com/words/were-react-hooks-a-mistake/
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus_web::launch::launch(app, vec![], Default::default());
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
let mut count = use_signal(|| 0);
|
||||
let mut started = use_signal(|| false);
|
||||
|
||||
let mut start = move || {
|
||||
if !started() {
|
||||
let alert = move || gloo_dialogs::alert(&format!("Your score was {count}!",));
|
||||
gloo_timers::callback::Timeout::new(5_000, alert).forget();
|
||||
}
|
||||
started.set(true); // this cannot be done inside condition or infinite loop
|
||||
};
|
||||
|
||||
rsx! {
|
||||
button {
|
||||
onclick: move |_event| {
|
||||
start();
|
||||
count += 1;
|
||||
},
|
||||
|
||||
if started() {
|
||||
"Current score: {count}"
|
||||
} else {
|
||||
"Start"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
requestIdleCallback and requestAnimationFrame implementation
|
||||
|
||||
These currently actually slow down our DOM patching and thus are temporarily removed. Technically we can schedule around rIC and rAF but choose not to.
|
|
@ -1,80 +0,0 @@
|
|||
//! This module provides some utilities around scheduling tasks on the main thread of the browser.
|
||||
//!
|
||||
//! The ultimate goal here is to not block the main thread during animation frames, so our animations don't result in "jank".
|
||||
//!
|
||||
//! Hence, this module provides Dioxus "Jank Free Rendering" on the web.
|
||||
//!
|
||||
//! Because RIC doesn't work on Safari, we polyfill using the "ricpolyfill.js" file and use some basic detection to see
|
||||
//! if RIC is available.
|
||||
|
||||
use futures_util::StreamExt;
|
||||
use gloo_timers::future::TimeoutFuture;
|
||||
use js_sys::Function;
|
||||
use wasm_bindgen::{prelude::Closure, JsCast, JsValue};
|
||||
use web_sys::{window, Window};
|
||||
|
||||
pub(crate) struct RafLoop {
|
||||
window: Window,
|
||||
ric_receiver: futures_channel::mpsc::UnboundedReceiver<u32>,
|
||||
raf_receiver: futures_channel::mpsc::UnboundedReceiver<()>,
|
||||
ric_closure: Closure<dyn Fn(JsValue)>,
|
||||
raf_closure: Closure<dyn Fn(JsValue)>,
|
||||
}
|
||||
|
||||
impl RafLoop {
|
||||
pub fn new() -> Self {
|
||||
let (raf_sender, raf_receiver) = futures_channel::mpsc::unbounded();
|
||||
|
||||
let raf_closure: Closure<dyn Fn(JsValue)> = Closure::wrap(Box::new(move |_v: JsValue| {
|
||||
raf_sender.unbounded_send(()).unwrap()
|
||||
}));
|
||||
|
||||
let (ric_sender, ric_receiver) = futures_channel::mpsc::unbounded();
|
||||
|
||||
let has_idle_callback = {
|
||||
let bo = window().unwrap().dyn_into::<js_sys::Object>().unwrap();
|
||||
bo.has_own_property(&JsValue::from_str("requestIdleCallback"))
|
||||
};
|
||||
let ric_closure: Closure<dyn Fn(JsValue)> = Closure::wrap(Box::new(move |v: JsValue| {
|
||||
let time_remaining = if has_idle_callback {
|
||||
if let Ok(deadline) = v.dyn_into::<web_sys::IdleDeadline>() {
|
||||
deadline.time_remaining() as u32
|
||||
} else {
|
||||
10
|
||||
}
|
||||
} else {
|
||||
10
|
||||
};
|
||||
|
||||
ric_sender.unbounded_send(time_remaining).unwrap()
|
||||
}));
|
||||
|
||||
// execute the polyfill for safari
|
||||
Function::new_no_args(include_str!("./ricpolyfill.js"))
|
||||
.call0(&JsValue::NULL)
|
||||
.unwrap();
|
||||
|
||||
let window = web_sys::window().unwrap();
|
||||
|
||||
Self {
|
||||
window,
|
||||
raf_receiver,
|
||||
raf_closure,
|
||||
ric_receiver,
|
||||
ric_closure,
|
||||
}
|
||||
}
|
||||
/// waits for some idle time and returns a timeout future that expires after the idle time has passed
|
||||
pub async fn wait_for_idle_time(&mut self) -> TimeoutFuture {
|
||||
let ric_fn = self.ric_closure.as_ref().dyn_ref::<Function>().unwrap();
|
||||
let _cb_id: u32 = self.window.request_idle_callback(ric_fn).unwrap();
|
||||
let deadline = self.ric_receiver.next().await.unwrap();
|
||||
TimeoutFuture::new(deadline)
|
||||
}
|
||||
|
||||
pub async fn wait_for_raf(&mut self) {
|
||||
let raf_fn = self.raf_closure.as_ref().dyn_ref::<Function>().unwrap();
|
||||
let _id: i32 = self.window.request_animation_frame(raf_fn).unwrap();
|
||||
self.raf_receiver.next().await.unwrap();
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
const requestIdleCallback =
|
||||
(typeof self !== 'undefined' &&
|
||||
self.requestIdleCallback &&
|
||||
self.requestIdleCallback.bind(window)) ||
|
||||
function (cb) {
|
||||
const start = Date.now();
|
||||
return setTimeout(() => {
|
||||
cb({
|
||||
didTimeout: false,
|
||||
timeRemaining: function () {
|
||||
return Math.max(0, 50 - (Date.now() - start));
|
||||
},
|
||||
});
|
||||
}, 1);
|
||||
};
|
||||
|
||||
const cancelIdleCallback =
|
||||
(typeof self !== 'undefined' &&
|
||||
self.cancelIdleCallback &&
|
||||
self.cancelIdleCallback.bind(window)) ||
|
||||
function (id) {
|
||||
return clearTimeout(id);
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.requestIdleCallback = requestIdleCallback;
|
||||
window.cancelIdleCallback = cancelIdleCallback;
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
use dioxus::prelude::*;
|
||||
use dioxus_web::Config;
|
||||
use wasm_bindgen_test::wasm_bindgen_test;
|
||||
use web_sys::window;
|
||||
|
||||
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
||||
#[test]
|
||||
fn makes_tree() {
|
||||
fn app() -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
div { h1 {} }
|
||||
div { h2 {} }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut dom = VirtualDom::new(app);
|
||||
let muts = dom.rebuild_to_vec();
|
||||
|
||||
dbg!(muts.edits);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn rehydrates() {
|
||||
fn app() -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
div { h1 { "h1" } }
|
||||
div { h2 { "h2" } }
|
||||
button {
|
||||
onclick: move |_| {
|
||||
println!("clicked");
|
||||
},
|
||||
"listener test"
|
||||
}
|
||||
{false.then(|| rsx! { "hello" })}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut dom = VirtualDom::new(app);
|
||||
dom.rebuild(&mut dioxus_core::NoOpMutations);
|
||||
let out = dioxus_ssr::render(&dom);
|
||||
|
||||
window()
|
||||
.unwrap()
|
||||
.document()
|
||||
.unwrap()
|
||||
.body()
|
||||
.unwrap()
|
||||
.set_inner_html(&format!("<div id='main'>{out}</div>"));
|
||||
|
||||
dioxus_web::launch::launch_cfg(app, Config::new().hydrate(true));
|
||||
}
|
Loading…
Reference in a new issue