diffHTML
v1.0.0-beta.29
An easy-to-use Virtual DOM built for the web!
diffHTML
v1.0.0-beta.29An easy-to-use Virtual DOM built for the web!
Middleware
While you can get very far with just the basic rendering features of diffHTML,
you may find yourself wanting to extend or hook into the Transaction flow. A
good way of hooking into the lifecycle is to use middleware. These are objects
or functions that are provided by the top-level
use()
API.
import { use } from 'diffhtml';
// Use the logger middleware
use(logger());
Writing middleware
Authoring middleware was designed to be straightforward for simple things like tracking when renders occur, what the previous and next VTrees look like, and what the given set of DOM updates were for the render.
While simple things are easy to access, the API allows for significantly more complex operations, such as:
- Creating new elements
- Changing the DOM synchronization logic
- Adopt elements/components from other frameworks
- XML transformations
- React to DevTools changes
Lastly, middleware can be used with the toString method. So if you are extra ambitious you can get your middleware to be fully cross-platform even during Server-Side-Rendering.
The code for a basic middleware looks as simple as:
import { use } from 'diffhtml';
use(transaction => {
console.log('Render transaction is starting');
return () => {
console.log('Render transaction is ending');
transaction.onceEnded(() => {
console.log('Render transaction has completed');
});
};
});
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 logging the render transaction flow.
use(() => ({ patches }) => {
console.log(patches);
});
Logger
Use with diffHTML to console.log
out render
Transaction
operations. This will nest
sub-component renders if they happen during a parent render.
npm install diffhtml-middleware-logger
Example
import { use } from 'diffhtml';
import logger from 'diffhtml-middleware-logger';
use(logger());
This is not a very performant middleware, so please do not use this in production where performance is critical. Use only in development or behind a flag.
Service Worker
While this does not really benefit from being a middleware, I made it as such since it looks nice in the use and can be disabled if the middleware is unsubscribed. I've added some developer niceties, like auto clearing the caches for development. It's also possible to disable the worker completely if you get annoyed with some behavior.
npm install diffhtml-middleware-service-worker
Example
import { use } from 'diffhtml';
import serviceWorker from 'diffhtml-middleware-service-worker';
// Defaults shown, these are all optional values.
use(serviceWorker({
url: '/service-worker.js',
scope: '/',
autoClearCaches: location.search.includes('diff_autoclear'),
disable: location.search.includes('diff_disable'),
quiet: location.search.includes('diff_quiet'),
options: {},
}));
Synthetic Events
Changes the event binding from inline event handlers like onclick = fn
to use
addEventListener
. Hooks are attached to the body
element and coordinated
using event delegation.
npm install diffhtml-middleware-synthetic-events
Example
import { use, html, innerHTML } from 'diffhtml';
import syntheticEvents from 'diffhtml-middleware-synthetic-events';
use(syntheticEvents());
function render() {
return html`
<div onclick=${e => console.log(e)} />
`;
}
// Binds the event on div using `addEventListener`.
innerHTML(document.body, render());
A good use case for this middleware is building a Chrome Extension where using
inline event handlers is not possible. Supports non-bubbling events via the
useCapture
flag.
Verify State
Asserts that a render properly updated the old Virtual Tree and the DOM. Will recursively search for inconsistencies, displays warnings unless debugging is enabled, then it throws errors instead.
npm install diffhtml-middleware-verify-state
Example
import { use } from 'diffhtml';
import verifyState from 'diffhtml-middleware-verify-state';
// Throw when debug is truthy (when location.search has `?debug`)
use(verifyState({ debug: location.search.includes('debug') }));
HTML Linter
Validates your passed in markup against rules established in the HTMLHint project.
npm install diffhtml-middleware-linter
Example
import { use } from 'diffhtml';
import linter from 'diffhtml-middleware-linter';
use(linter({
// Supported rules and their defaults.
rules: {
"tagname-lowercase": true,
"attr-lowercase": true,
"attr-value-not-empty": false,
"id-unique": true,
"src-not-empty": true,
"title-require": true,
"alt-require": true,
"id-class-value": "dash",
"style-disabled": false,
"inline-style-disabled": false,
"inline-script-disabled": false,
"attr-unsafe-chars": true,
"head-script-disabled": true,
},
renderErrors: true // by default is false
}));