Security News
NVD Backlog Tops 20,000 CVEs Awaiting Analysis as NIST Prepares System Updates
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
morphdom is a lightweight JavaScript library that efficiently morphs one DOM tree into another. It is useful for updating the DOM in a performant way, especially in scenarios where you need to apply changes to the DOM without reloading the entire page.
Basic DOM Morphing
This feature allows you to morph one DOM element into another. The `morphdom` function takes two arguments: the source element and the target HTML string or element. It efficiently updates the source element to match the target.
const morphdom = require('morphdom');
const fromNode = document.getElementById('from');
const toNode = document.getElementById('to');
morphdom(fromNode, toNode.innerHTML);
Preserve State
This feature allows you to preserve the state of certain elements during the morphing process. The `onBeforeElUpdated` callback can be used to prevent specific elements from being updated if they are already equal.
const morphdom = require('morphdom');
const fromNode = document.getElementById('from');
const toNode = document.getElementById('to');
morphdom(fromNode, toNode.innerHTML, {
onBeforeElUpdated: function(fromEl, toEl) {
if (fromEl.isEqualNode(toEl)) {
return false;
}
}
});
Custom Element Handling
This feature allows you to handle custom logic for discarding elements. The `onBeforeNodeDiscarded` callback can be used to prevent certain elements from being removed from the DOM.
const morphdom = require('morphdom');
const fromNode = document.getElementById('from');
const toNode = document.getElementById('to');
morphdom(fromNode, toNode.innerHTML, {
onBeforeNodeDiscarded: function(node) {
if (node.classList && node.classList.contains('no-discard')) {
return false;
}
}
});
Snabbdom is a virtual DOM library with a focus on simplicity, modularity, and performance. It allows you to create a virtual DOM tree and efficiently update the real DOM to match it. Compared to morphdom, Snabbdom provides a more comprehensive virtual DOM implementation and is often used in larger applications.
diffhtml is a library for diffing and patching the DOM. It provides a declarative way to update the DOM by comparing the current state with a new state and applying the minimal set of changes. diffhtml offers more features for complex DOM updates compared to morphdom.
domdiff is a minimal library for diffing and patching the DOM. It focuses on providing a lightweight solution for updating the DOM with minimal overhead. While it is similar to morphdom in terms of functionality, domdiff is more lightweight and may be suitable for simpler use cases.
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!
This module was created to solve the problem of updating the DOM in response to a UI component or page being rerendered. One way to update the DOM is to simply toss away the existing DOM tree and replace it with a new DOM tree (e.g., myContainer.innerHTML = newHTML
). While replacing an existing DOM tree with an entirely new DOM tree will actually be very fast, it comes with a cost. The cost is that all of the internal state associated with the existing DOM nodes (scroll positions, input caret positions, CSS transition states, etc.) will be lost. Instead of replacing the existing DOM tree with a new DOM tree we want to transform the existing DOM tree to match the new DOM tree while minimizing the number of changes to the existing DOM tree. This is exactly what the morphdom
module does! Give it an existing DOM node tree and a target DOM node tree and it will efficiently transform the existing DOM node tree to exactly match the target DOM node tree with the minimum amount of changes.
morphdom
does not rely on any virtual DOM abstractions. Because morphdom
is using the real DOM, the DOM that the web browser is maintaining will always be the source of truth. Even if you have code that manually manipulates the DOM things will still work as expected. In addition, morphdom
can be used with any templating language that produces an HTML string.
The transformation is done in a single pass and is designed to minimize changes to the DOM while still ensuring that the morphed DOM exactly matches the target DOM. In addition, the algorithm used by this module will automatically match up elements that have corresponding IDs and that are found in both the original and target DOM tree.
First install the module into your project:
npm install morphdom --save
The code below shows how to morph one <div>
element to another <div>
element.
var morphdom = require('morphdom');
var el1 = document.createElement('div');
el1.className = 'foo';
var el2 = document.createElement('div');
el2.className = 'bar';
morphdom(el1, el2);
expect(el1.className).to.equal('bar');
You can also pass in an HTML string for the second argument:
var morphdom = require('morphdom');
var el1 = document.createElement('div');
el1.className = 'foo';
el1.innerHTML = 'Hello John';
morphdom(el1, '<div class="bar">Hello Frank</div>');
expect(el1.className).to.equal('bar');
expect(el1.innerHTML).to.equal('Hello Frank');
NOTE: This module will modify both the original and target DOM node tree during the transformation. It is assumed that the target DOM node tree will be discarded after the original DOM node tree is morphed.
The morphdom(fromNode, toNode, options)
function supports the following arguments:
Node
)- The node to morphNode
|String
) - The node that the fromNode
should be morphed to (or an HTML string)Object
) - See below for supported optionsThe returned value will typically be the fromNode
. However, in situations where the fromNode
is not compatible with the toNode
(either different node type or different tag name) then a different DOM node will be returned.
Supported options (all optional):
Function(node)
) - A function that will called before a Node
in the from
tree has been discarded. If the listener function returns false
then the element will not be discarded.Function(node)
) - A function that will called when a Node
in the from
tree has been discarded and will no longer exist in the final DOM tree.Function(fromEl, toEl)
) - A function that will called when a HTMLElement
in the from
tree is about to be morphed. If the listener function returns false
then the element will be skipped.Function(fromEl, toEl)
) - A function that will called when the children of an HTMLElement
in the from
tree are about to be morphed. If the listener function returns false
then the child nodes will be skipped.var morphdom = require('morphdom');
var morphedNode = morphdom(fromNode, toNode, {
onBeforeNodeDiscarded: function(node) {
return true;
}
onNodeDiscarded: function(node) {
},
onBeforeMorphEl: function(fromEl, toEl) {
return true;
},
onBeforeMorphElChildren: function(fromEl, toEl) {
return true;
}
});
No, the DOM data structure is not slow. The DOM is a key part of any web browser so it must be fast. Walking a DOM tree and reading the attributes on DOM nodes is not slow. However, if you attempt to read a computed property on a DOM node that requires a relayout of the page then that will be slow. However, morphdom
only cares about the following properties of a DOM node:
node.firstChild
node.tagName
node.nextSibling
node.attributes
node.nodeType
node.nodeValue
Libraries such as a React and virtual-dom solve a similar problem using a Virtual DOM. That is, at any given time there will be the real DOM (that the browser rendered) and a lightweight and persistent virtual DOM tree that is a mirror of the real DOM tree. Whenever the view needs to update, a new virtual DOM tree is rendered. The new virtual DOM tree is then compared with the old virtual DOM tree using a diffing algorithm. Based on the differences that are found, the real DOM is then "patched" to match the new virtual DOM tree and the new virtual DOM tree is persisted for future diffing.
Both morphdom
and virtual DOM based solutions update the real DOM with the minimum number of changes. The only difference is in how the differences are determined. morphdom
compares real DOM nodes while virtual-dom
and others only compare virtual DOM nodes.
There are some drawbacks to using a virtual DOM-based approach:
The premise for using a virtual DOM is that the DOM is "slow". While there is slightly more overhead in creating actual DOM nodes instead of lightweight virtual DOM nodes, we are not seeing any noticeable slowness in our benchmarks. In addition, as web browsers get faster the DOM data structure will also likely continue to get faster so there benefits to avoiding the abstraction layer.
See the Benchmarks below for a comparison of morphdom
with virtual-dom.
There are many high performance templating engines that stream out HTML strings with no intermediate virtual DOM nodes being produced. On the server, rendering directly to an HTML string will always be faster than rendering virtual DOM nodes (that then get serialized to an HTML string). In a benchmark where we compared server-side rendering for Marko (with Marko Widgets) and React we found that Marko was able to render pages ten times faster than React with much lower CPU usage (see: Marko vs React: Performance Benchmark)
In theory, templating languages such as Marko could support two compiled outputs: one that produces HTML strings (for use on the server) and another that produces DOM nodes (for use in the browser). However, based on our benchmarks we see no reason to switch over to rendering DOM nodes. Rendering to an HTML string performs very well on both the server and in the browser and it simplifies template compilers.
morphdom
?morphdom
is being used in the following projects:
v5.0.0-beta+
) - Marko Widgets is a high performance and lightweight UI components framework that uses the Marko templating engine for rendering UI components. You can see how Marko Widgets compares to React in performance by taking a look at the following benchmark: Marko vs React: Performance BenchmarkNOTE: If you are using a morphdom
in your project please send a PR to add your project here
Below are the results on running benchmarks on various DOM transformations for both morphdom
and virtual-dom. This benchmark uses a high performance timer (i.e., window.performance.now()
) if available. For each test the benchmark runner will run 100
iterations. After all of the iterations are completed for one test the average time per iteration is calculated by dividing the total time by the number of iterations.
To run the benchmarks:
npm run benchmark
The table below shows some sample benchmark results when running the benchmarks on a MacBook Pro (2.8 GHz Intel Core i7, 16 GB 1600 MHz DDR3). The average time per iteration for each test is shown in the table below:
virtual-dom | morphdom | |
change-tagname | 0.01ms | 0.00ms |
change-tagname-ids | 0.02ms | 0.01ms |
data-table | 0.75ms | 0.29ms |
ids-nested | 0.01ms | 0.01ms |
ids-nested-2 | 0.02ms | 0.01ms |
ids-nested-3 | 0.08ms | 0.08ms |
ids-nested-4 | 0.03ms | 0.11ms |
ids-nested-5 | 0.03ms | 0.02ms |
ids-nested-6 | 0.02ms | 0.01ms |
ids-prepend | 0.01ms | 0.01ms |
input-element | 0.01ms | 0.06ms |
input-element-disabled | 0.00ms | 0.00ms |
input-element-enabled | 0.01ms | 0.01ms |
large | 1.01ms | 1.61ms |
lengthen | 0.02ms | 0.02ms |
one | 0.01ms | 0.00ms |
reverse | 0.02ms | 0.01ms |
reverse-ids | 0.02ms | 0.02ms |
select-element | 0.03ms | 0.02ms |
shorten | 0.01ms | 0.02ms |
simple | 0.01ms | 0.01ms |
simple-ids | 0.03ms | 0.02ms |
simple-text-el | 0.02ms | 0.01ms |
svg | 0.01ms | 0.02ms |
todomvc | 0.23ms | 0.31ms |
two | 0.01ms | 0.01ms |
NOTE: Safari 8.0.7 (10600.7.12)
Pull Requests welcome. Please submit Github issues for any feature enhancements, bugs or documentation problems. Please make sure tests pass:
npm test
ISC
FAQs
Morph a DOM tree to another DOM tree (no virtual DOM needed)
The npm package morphdom receives a total of 152,899 weekly downloads. As such, morphdom popularity was classified as popular.
We found that morphdom demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.
Security News
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.