Utility to stream HTML content into a live document.
npm install writable-dom
This module allows you to write a stream of raw HTML chunks into an existing element in the DOM. Each chunk of HTML is handled in a way that is similar to how browsers process and display it.
Specifically blocking assets, including stylesheets and scripts, prevent adding newly parsed nodes to the target element. This means that there are no flashes of unstyled content, and that scripts execution order follows the same rules as normal.
On top of that this module will look ahead for additional assets to preload while it is blocked.
The following examples fetch an HTML stream and place the content into a #root
container element.
import WritableDOMStream from "writable-dom";
const res = await fetch("http://ebay.com");
const myEl = document.getElementById("root");
await res.body
.pipeThrough(new TextDecoderStream())
.pipeTo(new WritableDOMStream(myEl));
The presented example relies on the WritableStream
s API.
An alternative API is also available to use in case legacy browsers not implementing WritableStream
s need to be supported.
The following is a version of the previous example implemented using the alternative API.
import writableDOM from "writable-dom";
const res = await fetch("https://ebay.com");
const decoder = new TextDecoder();
const reader = res.body.getReader();
const myEl = document.getElementById("root");
// create a writable object to stream data into.
const writable = writableDOM(myEl);
try {
while (true) {
const { value, done } = await reader.read();
if (done) {
// wait for blocking assets to finish.
await writable.close();
break;
}
// write partial chunks of html.
writable.write(decoder.decode(value));
}
} catch (err) {
// ensure the writable dom stops if there is an error.
writable.abort(err);
}
The module exposes a single default constructor function, once imported it can be used via one of the two following APIs.
import writableDOMStream from "writable-dom";
new WritableDOMStream(
target: ParentNode,
previousSibling?: ChildNode | null
): WritableStream
By instantiating a new object via the new
keyword on the constructor function, the generated object will be of type WritableStream<string>, which you can for example combine with your original stream via the pipeTo
method.
You can also provide previousSibling
to have all written HTML be placed after that node.
import writableDOM from "writable-dom";
writableDOM(
target: ParentNode,
previousSibling?: ChildNode | null
): Writable
Calling the function directly creates a new Writable
object which you can use to manually write HTML into the target
element.
Again, you can also provide previousSibling
to have all written HTML be placed after that node.
A Writable
object provides the following methods:
-
write(html: string): void
Writes a partial chunk of HTML content into thetarget
element. -
close(): Promise<void>
Indicates that no additional HTML is going to be written. Returns a promise that will resolve when all blocking assets have loaded and the content is being displayed in the document. You should not callwrite
after callingclose
. -
abort(err: Error): void
Prevents any additional HTML from being written into the document and aborts any blocking assets. You should not callwrite
after callingabort
.
This project adheres to the eBay Code of Conduct. By participating in this project you agree to abide by its terms.