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