The easy-to-use Virtual DOM, built for the web!

Welcome to diffHTML! A library created for anyone wanting to build a reactive web application. Lightweight and easy-to-use, it is authored in standards-compliant ES6 JavaScript.

You would use it in the same way as other web frameworks such as: React, Vue, and Svelte. You may want to look at these first, as they are backed by corporations and/or large communities.

Core features

Installing & importing

The source code is authored in valid ES6 and can be run without a transpiler in JavaScript runtimes that support the latest specification. The minified version can be run in an ES5 environment as it runs through a separate build step to make it compatible with UglifyJS.

Latest full version minified endpoints

Using this method will bring in the global minified UMD file. This includes the parser so it will be larger than the runtime build weighing at around 7.8kb min+gzip. Access the API through the window.diff global.

Latest runtime version minified endpoints

If you use the Babel transform, you will be able to use the runtime build instead. This converts html tagged template calls into createTree calls, which take in the Babel converted trees. This greatly reduces the bundle sizes. The base bundle size here is just 6kb min+gzip!

Installing into node_modules

JavaScript package management uses this folder and there are two many different clients that can install into. Two recommended ones are shown below:

This will create the following structure:

├── dist
│   ├── cjs # where all the CommonJS files are
│   ├── diffhtml.js
│   ├── diffhtml.min.js
│   ├── diffhtml-runtime.js
│   ├── diffhtml-runtime.min.js
│   └── es # where all the ESM files are
├── lib
├── package.json
└── README.md

Using a script tag

Use this tag in HTML to load diffHTML globally.

<script src="https://unpkg.com/diffhtml/dist/diffhtml.min.js"></script>

  const { innerHTML } = window.diff;

Loading just the runtime:

<script src="https://unpkg.com/diffhtml/dist/diffhtml-runtime.min.js"></script>

ES modules

You can import diffHTML directly over HTTP using the ES modules syntax. This is a new feature that isn't available in all browsers yet, but you can use them safely in nearly all modern browsers.

import { innerHTML } from 'https://unpkg.com/diffhtml?module';

To load just the runtime:

import { innerHTML } from 'https://unpkg.com/diffhtml/runtime?module';

Using import maps

Import maps are a new new feature available in modern Chrome that allow you to specify a configuration to import global names instead of using URLs or file paths directly.

For instance, you can convert:

import { innerHTML } from 'https://diffhtml.org/es';


import { innerHTML } from 'diffhtml';

Which will resolve to the same URL.

This is accomplished by adding a script tag to your web application that specifies the configuration as JSON. And looks something like this:

<script type="importmap">
  "imports": {
    "diffhtml": "https://diffhtml.org/es",
    "diffhtml/components": "https://diffhtml.org/master/diffhtml-components/dist/es"

Remember this is JSON so you cannot have trailing commas or use single quotes. It is also currently limited to being inline with the markup, it cannot be an external file.

Optimizing with Babel

GitHub repo link

The Babel plugin is useful after you have a working project and wish to optimize it further. The Babel plugin will perform numerous optimizations to your code depending on how it is written and structured. For instance, anytime you have an element that does not change it will be hoisted and reused instead of recreated every time. Any html tagged template calls will be converted to createTree calls. After code has been run through this plugin you will be able to pair with the runtime build.

and enable the use of the runtime build which decreases the file size further.

To use, install into your project as a dev dependency.

npm install -D babel-plugin-transform-diffhtml

Specify the plugin in the Babel configuration, usually a .babelrc or babel.config.js file:

  "plugins": ["babel-plugin-transform-diffhtml"]

Refer to the configuration documentation.

Writing middleware

You would write middleware when you need to extend diffHTML to do things that that were not originally intended. For instance, you could write logic that says whenever a specific attribute is present to execute some code on the element when it enters and leaves the DOM. You could log whenever diffHTML has a render operation scheduled, monitor transitions, and more.

A basic middleware looks as simple as:

import { use } from 'diffhtml';

use(() => {
  console.log('diffHTML render transaction is starting');

  return () => {
    console.log('diffHTML render transaction is ending');

There are several core middleware modules already written that you could use as a reference. A good starting one to look at is the Logger if you're interested in tracking the render transaction flow.

If you wanted to track when an element enters and leaves the DOM you could use the attached and detached transition states. You could also check the transaction when rendering is complete to see what is being attached and removed.

use(() => ({ patches }) => {
    if (patch.INSERT_BEFORE) {


Edit on GitHub