DEV Community

kwst
kwst

Posted on

Try “asm-dom” that is virtual DOM library by using WebAssembly

What is “asm-dom”?

https://github.com/mbasso/asm-dom
asm-dom is a virtual DOM library using WebAssembly. Its “diff” and “patch” algorithm of virtual DOM are implemented by WebAssembly and it’s a minimal implementation so it doesn’t have high function as React. I expect it is very fast by WebAssembly.

The date of the initial commit is 2017/2/26 so it’s a year old.
Copyright and Lisense includes the name of “snabbdom”. It maybe related to snabbdom.

Simon Friis Vindum, 2015 as part of project snabbdom

Usage

It can be written by C++ but I used JS like WEB in this time.

npm i --save asm-dom 
npm i -D arraybuffer-loader 

I added webpack and webpack-dev-server to bundle by webpack.

npm i -D webpack webpack-dev-server 

webpack.config is like this. I added arraybuffer-loader to load .wasm file. I refer to the document for JS.

var resolve = require('path').resolve; module.exports = env => { const dist = env.prod ? 'docs' : 'dist'; return { entry: './src/index.js', output: { filename: 'bundle.js', path: resolve(__dirname, dist), pathinfo: !env.prod, }, node: { fs: 'empty' }, devtool: env.prod ? 'source-map' : 'eval', devServer: { contentBase: resolve(__dirname, dist), historyApiFallback: true, compress: true, port: 9000 }, module: { loaders: [ { test: /\.wasm$/, loaders: ['arraybuffer-loader'] } ] } }; } 

VS "virtual-dom"

I compared speed of "asm-dom" with "virtual-dom" that is a virtual DOM library. I measured the time of replacing 30000 text elements of <div>. I used Chrome ver61.

"asm-dom" won

"asm-dom" is 2 times faster than "virtual-dom". I never imagined this result. WebAssembly is awesome. I would like to compare also only "diff" and "patch" algorithm of React.

asm-dom result
asm-dom result

virtual-dom result
virtual-dom result

The code for measuring

I uploaded the code into this.
You can define DOM like hyperscript so make nodes by h() and apply diff by patch() like as virtual-dom.

asm-dom code

import init from 'asm-dom'; init().then(asmDom => { const { h, patch } = asmDom; const root = document.getElementById('root'); let vnode = h('div', {}, []); patch(root, vnode); let cnt = 0; const id = setInterval(() => { console.time('apply patch in 30000 elements'); const list = []; for (let i = 0; i < 30000; i++) { list.push( h('div', {}, [ Math.random() + '' ]) ); } const newVnode = h('div', {}, list); patch(vnode, newVnode); vnode = newVnode; console.timeEnd('apply patch in 30000 elements'); cnt++; if (cnt >= 10) { clearInterval(id); } }, 100); }); 

virtual-dom code

const h = require('virtual-dom/h'); const diff = require('virtual-dom/diff'); const patch = require('virtual-dom/patch'); const createElement = require('virtual-dom/create-element'); let cnt = 0; let tree = h('div', {}, []); let rootNode = createElement(tree); document.body.appendChild(rootNode); const id = setInterval(function () { console.time('apply patch in 30000 elements'); const list = []; for (let i = 0; i < 30000; i++) { list.push( h('div', {}, [ Math.random() + '' ]) ); } const newTree = h('div', {}, list); const patches = diff(tree, newTree); rootNode = patch(rootNode, patches); tree = newTree; console.timeEnd('apply patch in 30000 elements'); cnt++; if (cnt >= 10) { clearInterval(id); } }, 1000); 

Top comments (0)