fastdom icon indicating copy to clipboard operation
fastdom copied to clipboard

Why fastdom?

Open oskarrough opened this issue 11 years ago • 20 comments

Fastdom sounds so efficient that I need to ask what the possible downsides are. Why is this not the default behaviour implemented in modern browsers?

you should wrap any DOM reads with fastdom.read and writes with fastdom.write. They will get batched & executed in next frame...

oskarrough avatar Oct 18 '13 16:10 oskarrough

The simple reason is that browsers are wired for sync ops. You can set offsetWidth (write) and then ask for its value (read) and that is allowed. FastDOM lets you opt out of that and makes everything async. That is you would get the old value of offsetWidth before the new one was set. That's one example, and there are many properties that would trigger layout that you can Google for.

Async is great, and it would be lovely if this were the normal behaviour. But things would break if this were the default. FWIW Dart actually does DOM updates async, not that it solves this issue, but just so you know there are places where async DOM updates are normal and don't require libraries like FastDOM.

paullewis avatar Oct 18 '13 17:10 paullewis

Would it be helpful to have an answer like this on the main readme?

wilsonpage avatar Oct 19 '13 11:10 wilsonpage

I think so. Setting out why this even a thing is going to help devs less familiar with the area.

paullewis avatar Oct 19 '13 11:10 paullewis

Sorry to resuscitate the issue but I have a question:

What's the difference between using requestAnimationFrame directly and using fastdom?

renatoi avatar Feb 26 '14 18:02 renatoi

Using rAF might be OK for very small issues, but it doesn't ensure you won't be interleaving DOM read and writes, which is the thing we want to avoid.

How can you be sure that another part of your app hasn't scheduled conflicting work for the same frame?

FastDOM 'globally' coordinates when your read/write tasks are run, meaning that they are always run in the most performant way. All you have to know is that when your callback fires, the job is done :)

wilsonpage avatar Mar 03 '14 14:03 wilsonpage

how does the performance of fastdom compare to virtualdom?

serapath avatar Feb 06 '15 19:02 serapath

A virtual DOM library could consume a library like Fastdom to help it schedule operations at the correct time.

A virtual DOM library may also do a lot more. Think of fastdom as a lower level tool and a virtual DOM library as higher level abstraction.

All performance comparisons are relative. You'd need to try for yourself.

W. On 7 Feb 2015 03:57, "serapath" [email protected] wrote:

how does the performance of fastdom compare to virtualdom?

— Reply to this email directly or view it on GitHub https://github.com/wilsonpage/fastdom/issues/35#issuecomment-73302141.

wilsonpage avatar Feb 07 '15 02:02 wilsonpage

It might sound silly (just naming and curiosity) but why measure and mutate functions instead of read and write?

Forget about it, I think I know why.

leandromoreira avatar Jun 02 '16 17:06 leandromoreira

I think they are a little clearer in their intent. For example, you can 'read' an via .getAttribute() without making DOM 'measurements'. With 'mutate' I also feel it's more explicit. Sounds more damaging and should be treated with care.

wilsonpage avatar Jun 03 '16 15:06 wilsonpage

what I don't understand why do we need a library when browser actually queue dom operations before doing a repaint.

allyraza avatar Nov 22 '17 06:11 allyraza

@allyraza because the browser won't stop you breaking that behaviour. If you mutate some styles and then request -- say -- offsetLeft, the browser will run layout at that point. So while it's true that browsers do enqueue DOM operations, and that by default they will get applied in a batch, it's also true that you can break that behaviour with JavaScript, and that's what FastDOM is attempting to help with.

paullewis avatar Nov 23 '17 09:11 paullewis

I see a lot of performance solutions suggest a double/inner raf, but fastdom isn't using that technique. Is there a reason? I presume it was tried and measured.

crazy4groovy avatar Jan 12 '18 03:01 crazy4groovy

Interesting, can you give more detail/links?

wilsonpage avatar Jan 16 '18 12:01 wilsonpage

https://stackoverflow.com/questions/44145740/how-does-double-requestanimationframe-work

crazy4groovy avatar Jan 17 '18 23:01 crazy4groovy

This is a really interesting find, I've been giving it some thought. IIUC the issue is that if the DOM is manipulated outside of rAF and then you schedule a rAF with some other work inside, when browser will not actually paint the output of the DOM manipulation until that next frame, so essentially both tasks can end up running in the same frame.

So this issue is really about running blocking code inside rAF handlers delaying the browser beginning animations. I think we need a concrete example to make sense of this; so let's take clicking a navigation button, loading some data and navigating:

button.addEventListener('click', () => {
  fastdom.mutate(() => {
    button.classList.toggle('ripple');
    setTimeout(loadDataAndNavigateTo('some-page'));    
  });
});

I'm mutating the DOM and then, scheduling the loading and navigation at the end of the task queue so that is doesn't block the animation from starting. You could optionally use rAF instead of setTimeout(), but then you risk blocking other animations and render work.

This is a bit gross looking, I think I'd rather have a way to run something after the fastdom task is complete (AKA the animation has begun). Like:

button.addEventListener('click', async () => {
  await fastdom.mutate(() => button.classList.toggle('ripple'));
  loadDataAndNavigateTo('some-page');
});

That would require than we return a Promise once the fastdom task has been run, and might make this kind of use-case a bit prettier. We'd have to make sure this was after the internalrAF is fully complete.

Does that make sense? Have I understood the problem? :)

wilsonpage avatar Jan 22 '18 22:01 wilsonpage

That's an interesting thought. Honestly I don't know enough low-level to give an opinion, but returning a "blocking" promise that resolves when the mutation is complete makes sense.

I was just looking particularly at https://github.com/wilsonpage/fastdom/blob/master/fastdom.js#L158 and wondered if fastdom.raf(fastdom.raf(flush.bind(null, fastdom))); would be more performant? I think only empirical perf tests would determine that.

crazy4groovy avatar Jan 24 '18 21:01 crazy4groovy

Is this still a commonly (and more so recommended) library in 2019? With render, layout and paint speeds essentially so fast and with RAF, just wondering if this great library is still recommended? Maybe the benefits of batch reads and writes persist no matter how fast V8 engine or device CPU are?

Mapiac avatar Mar 05 '19 21:03 Mapiac

I hope fastdom disappears over time. I wouldn't reach for fastdom without diagnosing that you have a render per issue with your app. As with everything it depends. If jank is still a think on the mobile web, then there will likely be a place for fastdom.

If the DOM is abstracted away from you via a framework like React, you probably don't need fastdom.

wilsonpage avatar Mar 07 '19 21:03 wilsonpage

Thanks. Not using any VDOM or really any frameworks @wilsonpage. Just Cordova. Long scrolling lists and unfortunately large DOM even though we have made significant strides to reduce. However we've had FastDOM in for years and I was considering taking it out in consideration of the advancements these past CPL years.

Mapiac avatar Mar 08 '19 01:03 Mapiac

For long scroll you may want to check virtual scroll technic.

yellow1912 avatar Oct 06 '20 14:10 yellow1912