mrkeyoor.com_
Wed 23 Sept 12:34 UTC
npmWeb Frontendupdated 23 Sept 2026

dom-serialize review

dom-serialize 2.2.1 turns browser DOM objects into HTML-shaped strings, including Text, Attr, Comment, Document, DocumentFragment, NodeList, and arrays as well as elements. Its special feature is a bubbling `serialize` event fired for every visited node. A listener can replace that node's output, substitute another Node, or cancel it. The package is useful when that event hook is already part of a browser pipeline, but it is a CommonJS artifact from 2015 with HTML-specific casing and void-element rules.

Verdict

Our browser bundle for dom-serialize 2.2.1 measured 43.7 KB minified and 15.5 KB gzipped, and the package still has no types or exports map. Keep it for its per-node event override in an existing browser stack; choose a native or tree-specific serializer for new code.

We installed it

Lab card: what happened when we installed dom-serializeScreenshot of dom-serialize documentation
Install✓ · 1.6s22 packages on disk · 2 MB
ImportESM import works · require() works · CommonJS package
Browser15.5 KBgzipped (43.7 KB minified), bundled with esbuild
Typesno TypeScript types found
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does dom-serialize install cleanly?

Yes. In a fresh container with an empty cache, npm install dom-serialize finished in 2 seconds, leaving 22 packages and 2 MB on disk. npm audit reported no known vulnerabilities.

How much does dom-serialize add to a browser bundle?

15.5 KB gzipped (43.7 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does dom-serialize work with both ESM and CommonJS?

Yes. Both import 'dom-serialize' and require('dom-serialize') worked in Node 22 in our run. The package is published as CommonJS.

Does dom-serialize include TypeScript types?

No type declarations were found in our install, so TypeScript users need their own declarations.

dom-serialize or w3c-xmlserializer: which should you use?

w3c-xmlserializer: Use it for specification-oriented XML serialization of DOM nodes. Our browser bundle for dom-serialize 2.2.1 measured 43.7 KB minified and 15.5 KB gzipped, and the package still has no types or exports map.

When should you not use dom-serialize?

You only need an element's markup in a modern browser, where outerHTML avoids 4 runtime dependencies and an event dispatched per node

API stability4/5Version 2.2.1 still exports one main function plus eight named serializers, and the source keeps the same event contract described by the README: listeners write `detail.serialize` or cancel the event. That surface has stayed fixed since the 2015 npm release. The score reflects predictable legacy behavior, though there is no compatibility policy, namespace contract, or maintained release line to distinguish deliberate stability from code that simply stopped changing.
Docs2/5The README identifies eight supported input shapes and explains the bubbling event override with executable-looking examples. It does not document the eight named helper exports, Node and DOM-emulator setup, the CommonJS-only packaging, missing TypeScript declarations, namespace behavior, or unsupported node types. Its main callback example writes `event.detail.serialze`, a typo that prevents the documented replacement branch from working when copied.
Maintenance1/5npm's current release remains 2.2.1, while GitHub reports the repository's last push on 2019-08-03. The project is still open and npm does not mark it deprecated. Even so, no recent release carries modern packaging, declarations, or compatibility work. A package that dispatches events throughout a DOM walk needs regression coverage across browser changes, and this repository gives adopters little evidence that such updates will arrive.
Ecosystem2/5The registry counted 3,253,465 downloads last week, yet the source repository has only 38 stars and the package still depends on an older four-module browser stack. There is no plugin system beyond ordinary DOM events, no declaration package in the release, and no framework-specific integration documentation. The download volume points to substantial transitive legacy use, while the surrounding developer ecosystem is narrow.

Use it if

  • Your input mixes elements, text nodes, comments, fragments, documents, NodeLists, and arrays under one serializer
  • A parent listener needs to redact or replace descendant markup through the package's bubbling `serialize` event
  • You are maintaining code whose output and extension points already depend on dom-serialize 2.2.1
  • A synchronous browser-side serializer is acceptable and every replacement string comes from trusted code
Skip it if

Setup reality

We installed dom-serialize 2.2.1 in our sandbox in 1.6 seconds. It left 22 packages and 2 MB on disk, while npm audit found 0 known vulnerabilities across all four severity levels. The package itself is 56 KB unpacked, declares 4 direct dependencies and 0 peer dependencies, and uses the MIT license. No native compiler, credential, or config file appeared.

The entry point is CommonJS and has no exports map. Both require() and ESM import worked in our Node 22 checks, though we found no TypeScript declarations. A browser build that imported the whole package measured 43.7 KB minified and 15.5 KB gzipped. Node does not supply the DOM objects this code expects, so server use also needs a separate DOM implementation.

Serialization is synchronous and walks the tree recursively. Each Node receives a serialize CustomEvent before normal output is chosen. Set event.detail.serialize to a string or replacement Node, or call preventDefault() to omit the node. Replacement strings are inserted as markup without escaping. The README's callback sample contains serialze; that spelling does nothing. Use the full serialize property name.

The output follows the package's own HTML rules rather than a namespace-aware browser round trip. Element names are lowercased, known void elements receive no closing tag, and unsupported node types return an empty string. Text and attribute values pass through ent, while comments are wrapped directly. Test output against the DOM implementation and node types your application actually supplies.

Patterns

Serialize an element's outer markup serialize-element

const serialize = require('dom-serialize');

const el = document.createElement('p');
el.textContent = 'A & B';
console.log(serialize(el));
// <p>A &amp; B</p>

Text nodes encode ampersands and angle brackets. The element name is converted to lowercase.

Encode a standalone text node serialize-text-node

const text = document.createTextNode('<tag> & text');
const output = serialize(text);
// &lt;tag&gt; &amp; text

A Text node needs no wrapper. Quote characters are not special in text content under this encoder.

Join a fragment without adding a tag serialize-fragment

const part = document.createDocumentFragment();
part.append(document.createTextNode('before'));
part.append(document.createElement('br'));
part.append(document.createTextNode('after'));
console.log(serialize(part));

A DocumentFragment emits only its children, and `br` is written without a closing tag.

Serialize matching nodes in document order serialize-node-list

const rows = document.querySelectorAll('tr.selected');
const html = serialize(rows);

Objects with a numeric `length` and no `nodeType` are treated as lists and concatenated by index.

Redact one node with an event listener replace-node-output

const secret = document.querySelector('[data-secret]');
secret.addEventListener('serialize', event => {
  event.detail.serialize = '<span>[redacted]</span>';
});
const html = serialize(secret.parentNode);

The replacement string is inserted verbatim. Escape user-controlled content before assigning it to `detail.serialize`.

Cancel serialization for private descendants omit-descendant

const root = document.querySelector('main');
root.addEventListener('serialize', event => {
  if (event.serializeTarget.matches?.('[data-private]')) {
    event.preventDefault();
  }
});
const html = serialize(root);

The event bubbles through real DOM ancestry. Calling `preventDefault()` with no replacement produces an empty string for that node.

Attach a callback for one serialization customize-one-call

const html = serialize(root, event => {
  if (event.serializeTarget.matches?.('[data-summary]')) {
    event.detail.serialize = '...';
  }
});

The package removes this listener after the call. Use `serialize`, not the misspelled `serialze` property shown in the README sample.

Send a mode to delegated listeners pass-context

root.addEventListener('serialize', event => {
  if (event.detail.context === 'email' && event.serializeTarget.nodeName === 'VIDEO') {
    event.detail.serialize = '<a href="/watch">Watch</a>';
  }
});
const email = serialize(root, 'email');

Context is arbitrary caller data stored at `event.detail.context`; dom-serialize does not inspect or validate it.

Substitute another DOM node replace-with-node

const html = serialize(root, event => {
  if (event.serializeTarget.nodeName === 'TIME') {
    event.detail.serialize = document.createTextNode(event.serializeTarget.dateTime);
  }
});

A replacement with a numeric `nodeType` is serialized recursively and can trigger another `serialize` event.

Call the attribute helper directly serialize-attribute

const link = document.createElement('a');
link.setAttribute('title', 'A & "B"');
const attr = serialize.serializeAttribute(link.attributes[0]);

The CommonJS function carries named helpers as properties. Those helpers are present in source but absent from the README API section.

Include a document doctype serialize-document

const type = document.implementation.createDocumentType('html', '', '');
const doc = document.implementation.createDocument(null, 'html', type);
console.log(serialize(doc));
// <!DOCTYPE html><html></html>

Document serialization joins child nodes. Element handling still uses the package's lowercase HTML rules.

Alternatives

PackageRegistryPick it when
w3c-xmlserializernpmUse it for specification-oriented XML serialization of DOM nodes.
dom-serializernpmUse it when the tree comes from htmlparser2, domhandler, or Cheerio.
serialize-javascriptnpmUse it to encode JavaScript values into source text rather than to walk DOM nodes.

More web frontend guides

postcss · react · react-dom · tailwindcss · htmlparser2 · tailwind-merge · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.