I have read few articles regarding the Real DOM and Virtual. But still, I am having confusion about understanding the concept of Real DOM and Virtual DOM.
When we update any element in a webpage, does it render the whole web page or just that specific part of the page? For example - If I have a paragraph and a button and I want to change the color of a paragraph with a button click then what will happen, will the browser render the whole page or just that part of the page in REAL DOM.
If it just re-render the specific part only then why do we need to use the virtual dom in react?
If you write careful code modifying the color of the paragraph on the real dom, then the browser will only have to do a minimal amount of work. The entire page shouldn't need to reflow in most cases. But as your website gets more complicated, the modifications you're making to the dom get more complicated as well, and it becomes easier to make mistakes which can force the browser to do expensive updates.
The purpose of the virtual dom is to let you write code without worrying about how to update the real dom in an optimal way. React does comparisons for you using the virtual dom (ie, objects in memory describing the page), and then figures out the minimum set of changes to make to the real dom.
So the virtual dom isn't going to be faster than carefully crafted manual updates. But it makes it very easy to write pretty fast code.
Related
How is React's Virtual DOM able to only render a certain part of the DOM & keep the rest of the tree?
Not sure if I'm correct, but if I change content of a Div in a normal HTML file, I would have to refresh the page to see the changes, right? Meaning I would have to repaint the whole thing, recreate the whole DOM tree again. I can't just directly update "only" the Div element myself. I will need to refresh the page & recreate the whole tree.
I know what Virtual DOM is, how it compares new version to it's old, diffing & stuff like that. I also read the reconciliation document, but that didn't answer my question as well. What happens after React has the new Virtual DOM it needs to convert into the Real DOM?
What I'm trying to ask is: Essentially, React is just plain HTML & JS, having to end up as the real DOM. So how do they only update a Single Div element in the DOM instead of needing to reload the whole page? Because if we did that manually in HTML, the whole page would need to be refreshed to see changes & as far as I know, we can't just update one part of it ourselves like React does.
The short answer is that you don't have to reload the page to update the DOM tree. You can try this yourself by inspecting any element and edit its contents. React can also update the DOM in a similar way. It's instant as the contents are in memory and not saved on a file (which would need to be reloaded).
Example of a DOM update :)
You can update the DOM with javascript. the reason why you need to reload the page when you update a file and react doesn't is because when you load a page in the browser, the browser loads the page's files into it's memory/your ram executes the code (html, css and javascript). reacts code for updating the DOM is in the page's javascript.
However, if you change the html in a file, chrome doesn't have an idea so wouldn't know, hence you would have to reload the page for chrome to load the new page resources into it's memory and execute whatever code there is.
Came across below statement in one or other form on google
Each time the underlying data changes in a React app, a new Virtual
DOM representation of the user interface is created.This is where
things get interesting. Updating the browser’s DOM is a three-step
process in React.
Whenever anything may have changed, the entire UI will be re-rendered
in a Virtual DOM representation.
The difference between the previous
Virtual DOM representation and the new one will be calculated.
The
real DOM will be updated with what has actually changed. This is very
much like applying a patch.
I am new to React and would like to understand above how above three points used to to work in pre-React Era say in jQuery (or native JS).
jQuery
HTML was constructed on server side, sent back to browser. Browser will parse, render, layout and paint it.
Say any new DOM element is created or hidden either on some user event or on load.
Will jQuery recreate the complete DOM? From third point stated above looks like React just update the DOM for only the part that has been changed but other system (primarily jQuery or native JS) will recreate the complete DOM. Is that correct?
Is the third point true only for DOM changes or even when state of any UI component changes like filling the text box/dropdown etc?
Will jquery recreate the complete DOM ? From third point stated above looks like React just update the DOM for only the part that has been changed but other system(primarily jquery or native js) will recreate the complete DOM. Is that correct?
jQuery
No, jQuery doesn't recreate the DOM. Instead it navigates the DOM tree with selectors provided to make the appropriate changes. This makes jQuery very similar to React, but its performance issues come with the way the code was designed and it's heavy usage of the facade design pattern. This is normal for any larger library that needs to support multiple browsers like Chrome, Firefox, Opera, etc.
Angular 1
A framework that used to repaint the entire DOM was Angular 1. The client would make some changes, and rerender whenever $scope.apply or $scope.digest was called. This, combined with a huge number of listeners on large pages for two way data-binding was one of the big reasons why Angular had to undergo significant changes to stay competitive. Angular 8 is probably equivalent to React, but one has seen more adoption then the other.
React
React only updates the DOM that was changed. This is part of its "secret sauce". Along with its component centric architecture and early adoption of one way data-binding, it's seen a lot of success. Arguably React is starting to get more bloated since there's such wide adoption. This is normal for any project that gets mainstream usage. It's only a matter of time until people view React as a ton of performance problems and we'll create a new framework.
Alternatives
There are even faster frameworks than React, such as Elm lang. Nothing ever beats pure Javascript (e.g. document.querySelector()) since at their core, all frameworks use it. At that point you start hitting other trade offs such as lack of external libraries you can depend on, or difficulty in maintaining large front end codebases.
Is the third point true only for dom changes or even when state of any UI component changes like filling the text box/drop down etc ?
For jQuery or pure JS the third point is not true. There's a custom on-click handler of some sort that will run a function that makes a small change.
For something like Angular, that could be true if there are changes to scope that trigger a repaint. The same applies for React. If your submit button is supposed to redirect you to a completely different page, it will basically be repainting the DOM.
in react js in reander it create virtual DOM compare with browser DOM and update browser DOM. Rather than having virtual DOM why not to update directly in browser DOM.
Performance. Reading/writing to DOM is very expensive. It is much faster to calculate changes on JS data structure and then just do minimal amount of changes on real DOM. Except for some special cases you can avoid reading browser DOM alltogether thats why react is so fast.
Check this simple benchmark as you can see reading is not expensive. Writing is also not expensive but reading and writing is crazy expensive. (updateNode function does reading and writing)
Image is taken from this talk which I really recommend.
The DOM is made up of nodes that are rendered by your browser. As your application receives input from the user, it has to change certain nodes in order to show it's response (Ex- A button turning blue from red when the user clicks on it). Now, DOM is not good at doing anything smart. So, any time anything changes, it will re-render every node from scratch. This is a costly process.
React adds the brains to DOM by telling the DOM which node to render and which node to leave as it was. (Ex- Except the button, everything else in the UI should not change). This is done by storing the state of your DOM in JS in the form of nested objects (Forming a tree like strcuture). Changes to specific parts of this object will help React figure out which part of the DOM tree actually needs to be re-rendered. This is done using the concept of immutability which is very nicely explained in the ReactJS docs. So it basically diffs the new object with the old one and tells the DOM to make changes to specific nodes ONLY, thus improving performance by many folds.
I have 2 JS variables. before and after. They contains the SAME html document, but have some modification. About 1%-10% change between them. I want to update the body from before to after. The variablesbefore and after are raw string.
I can do something like that:
document.documentElement.innerHTML=after
The problem is that if I render this way it not look good. The render takes time, and there is a white screen between the renders. I want to show the user 10 modification in a second (video of modifications)
So what I want to do. I want to search and find only the elements that changed only by analyze the HTML text of before and after.
My way of solution:
I can find the changes and the position in the text using Javascript Library for diff & match & patch.
The question is:
After I find the text changes. How to find only the elements who changed. I update only those elements.
I thought, maybe to create a range, that contains every change, and update the range, but how exactly to do that?
If anything unclear, please comment, I will explain better.
I found a very good library for it: https://github.com/patrick-steele-idem/morphdom
Lightweight module for morphing an existing DOM node tree to match a
target DOM node tree. It's fast and works with the real DOM—no virtual
DOM here!
Very easy to use, and doing exactly what I need
If I have understood your question correctly, then what I would have done is,
1) Make a new object (view Object) which will control the rendering of DOM elements. (Similar to MVC)
2) In this object, I would have created 3 functions.
a) init function (contains the event-handlers)
b) render1 function (which will contain elements in before element)
c) render2 function (which will contain elements in after element)
Whenever there is an event where I need to change the HTML of a class/id/body/document, I will change that in init function and call render2 function which contains the after element.
This should not give any error, however the browser has to work to render all the page, but rendering can be divided over multiple elements of document. So, whenever you need to render a part of document, make separate render functions.
p.s. there can be different approaches.
You must implement the LCS(Longest Common Subsequence). To understand better of this algorithm you can watch this youtube video. Also It's easier to first study Longest Common Substring.
I think I have a solution. virtual-dom can do the work for me. I can create two VTree, make a diff, and apply a patch.
From the documentation of virtual-dom:
virtual-dom is what I need.
Manual DOM manipulation is messy and keeping track of the previous DOM
state is hard. A solution to this problem is to write your code as if
you were recreating the entire DOM whenever state changes. Of course,
if you actually recreated the entire DOM every time your application
state changed, your app would be very slow and your input fields would
lose focus.
virtual-dom is a collection of modules designed to provide a
declarative way of representing the DOM for your app. So instead of
updating the DOM when your application state changes, you simply
create a virtual tree or VTree, which looks like the DOM state that
you want. virtual-dom will then figure out how to make the DOM look
like this efficiently without recreating all of the DOM nodes.
virtual-dom allows you to update a view whenever state changes by
creating a full VTree of the view and then patching the DOM
efficiently to look exactly as you described it. This results in
keeping manual DOM manipulation and previous state tracking out of
your application code, promoting clean and maintainable rendering
logic for web applications.
https://github.com/Matt-Esch/virtual-dom
I'm developing a single page application that uses a lot of widgets (mainly grids and tabs) from the jqWidgets library that are all loaded upon page load. It's getting quite large and I've started to notice after using (I emphasize using because it doesn't start to lag after simply being open for any amount of time, but specifically, after opening and closing a bunch of tabs on my page, each tab containing multiple grids loaded thru Ajax that have multiple event listeners tied to each) the site for a couple minutes the UI becomes quite slow and sometimes non-responsive, when the page is refreshed everything works smooth again for a few minutes then back to laggy. I'm still testing on localhost. My initial reaction was that the DOM has too many elements (each grid creates hundreds of divs! And I have a lot of them) so event listeners which are tied to IDs have to search through too many elements and become slow. If this is the case it won't be too hard to fix, is my assumption likely to be the culprit or do I have worse things to fear?
UPDATE: here are captures of the memory time line and heap snapshot. On the memory timeline there was no interaction with the site, the two large increases are page refreshes, the middle saw tooth section is just letting my site idle.
Without seeing any code examples it doesn't sound too bad.
If you have a LOT of jQuery selectors try and make those specific as possible. Especially if you're selecting a lot of items a lot of the time.
For example, if you have a bunch of class "abc", try and specify before that where to look - e.g. are they only found within table cells? are they only found within paragraph tags? The more specific you make your selector the better as if you specify the selector like this:
$('.class')
Then it will search the entire DOM for anything that matches .class, however, if you specify it as follows: $('p .class') then it will only search all paragraph tags for the class.
Other performance killers are wiring up events and then never removing them. If you have any code that removes elements that have event handlers attached to them then best practice is to remove the event handlers when the element is removed. Otherwise you will start piling up orphaned events.
If you are doing a large single page application look to a library like backbone (http://backbonejs.org/) or angular (http://angularjs.org/) to see if this can help you - they alleviate a lot of these issues that people who use plain jQuery will run in to.
Finally, this post (http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/) is seriously good at outlining out you can write fast, efficient javascript and how to avoid the common performance pitfalls.
Hope this helps.
It does sound like you have a memory leak somewhere. Are you using recursion that's not properly controlled or do you have loops that could be ended early, but you fail to break out of them when you find something you're looking for before the loop naturally ends. Are you using something like this:
document.getElementById(POS.CurrentTableName + '-Menus').getElementsByTagName('td');
where the nodelist returned is huge and you only end up using a tiny bit of it. Those calls are expensive.
It could be your choice of architecture also. Hundreds of divs per grid doesn't sound manageable logically by a human brain. Do you address each div specifically by id or are they just an artifact of the lib you're using and are cluttering up the DOM? Have you checked the DOM itself as you're using it to see if you're adding elements in the hinterland by mistake and cluttering up the DOM with junk you don't use causing the DOM to grow continuously as you use the app. Are you adding the event handlers to the elements numerous times instead of just once?
For comparison, I too have a single page app (Google-Chrome App - Multi currency Restaurant Point of Sale) with anywhere from 1,500 to 20,000 event handlers registered making calls to a sqlite back end on a node.js server. I used mostly pure JS and all but 50 lines of the HTML is written in JS. I tie all the event handlers directly to the lowest level element responsible for the event. Some elements have multiple handlers (click, change, keydown, blur, etc).
The app operates at eye blink speed and stays that fast no matter how long its up. The DOM is fairly large and I regularly destroy and recreate huge portions of it (a restaurant table is cleared and recreated for the next sitting) including adding up to 1,500 event handlers per table. Hitting the CLEAR button and it refreshing the screen with the new table is almost imperceptible, admittedly on a high end processor. My development environment is Fedora 19 Linux.
Without being able to see your code, its a little difficult to say exactly.
If the UI takes a little bit before it starts getting laggy, then it sounds likely that you have a memory leak somewhere in your JavaScript. This happens quickly when using a lot of closures as well as nested function and variable references without cleaning them up when your done with them.
Also, event binding to many elements can be a huge drain on browser resources. If possible, try to use event delegation to lower the amount of elements listening to events. For example:
$('table').on('click','td', myEventHandler);
Be careful to make sure that event bindings only occur once as to avoid actions being unintentionally fired many times.
Good luck!