Chore: remove old cruft in web crate (#2957)

This commit is contained in:
Jonathan Kelley authored and GitHub committed 2024-09-13 12:54:28 -07:00
1 parent c7124e41fb
commit c5f00bf7d4
8 files changed
-303

No files matched your search

-35
View File
@@ -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
-10
View File
@@ -1,10 +0,0 @@
Examples
========
# Hydrate
- `hydrate` show hydrate
# Async
- `timeout_count` button to add count and show count in the future
-57
View File
@@ -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));
}
-34
View File
@@ -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"
}
}
}
}
-3
View File
@@ -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.
-80
View File
@@ -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();
}
}
-28
View File
@@ -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;
}
-56
View File
@@ -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));
}