npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vdomini

v3.3.1

Published

mini jsx virtual dom

Readme


Install

$ npm i vdomini

Or directly from jsDelivr:

/** @jsx h */
/** @jsxFrag Fragment */
import { h, Fragment, render } from 'https://cdn.jsdelivr.net/gh/stagas/vdomini/vdomini.min.js'

Goals

  • Minimal-to-zero API.

  • Fast. Stable. Predictable.

  • No surprises!

  • Compact. Readable. Hackable.

  • Minimal error surface - With code that tries to do as little as possible there can only be a handful of ways that something can go wrong and when it does it won't be because "issue #47665" hasn't been resolved yet.

  • When an error occurs you can inspect it, you're always one navigation away from its readable source code and the understanding of what caused it and possibly how to solve it.

  • No bells and whistles - All operations are as close as possible to the Real DOM(tm). No fibers, monads, queues, portals, no tons of layers of complexity between your intention and the operation.

  • No learning curve - You already know how to write HTML and to manipulate it using JavaScript. This is only abstracting a few DOM operations, which you also already know.

  • No setup - There are no plugins, transformers, transpilations that you need to learn or specific tools you need to use, besides TypeScript, which is excellent. If you're setup with TypeScript, then this is simply one npm install away. It's more like a library than a framework.

Features

  • Fast.
  • Tiny. 1.5kb brotli.
  • JSX with virtual dom.
  • Functional components with props, like usual from React.
  • Keyed lists with fast reconciliation only touching the items that changed.
  • Refs - Passing any object to the ref attribute will be injected a current property that corresponds to the live dom element.
  • Reactive Hooks - Only the function component and its children where the hook was captured are going to be rerendered when it triggers.
  • BYOB - The hook API is simply holding a reference and using the trigger function. Any kind of hook can be implemented using these primitives. The very basic ones are included simply for convenience and as an example.

Example

/** @jsx h */
/** @jsxFrag Fragment */

import { h, Fragment, render, useCallback } from 'vdomini'

let count = 0

const Counter = ({ count }) => {
  const inc = useCallback(() => count++)
  const dec = useCallback(() => count--)
  return (
    <>
      count is: {count}
      <br />
      <button onclick={inc}>increase</button>
      <button onclick={dec}>decrease</button>
    </>
  )
}

render(<Counter {...state} />, document.body)

A more complete example can be seen here.

API

Table of Contents

render

src/render.ts:577-579

Renders a virtual node on an html Element.

render(<p>hello world</p>, document.body)

Parameters

  • vNode VNode The virtual node to render
  • el Element The target element to render on

useHook

src/hooks.ts:20-26

Returns a callback that will trigger a rerender on the current component.

let clicked = 0
const Foo = () => <>
  {clicked++}
  <button onclick={useHook()}>click me</button>
</>

Returns any The hook callback

useCallback

src/hooks.ts:46-53

Wraps a function along with a hook so when called will also trigger that hook.

let clicked = 0
const Foo = () => {
  const inc = useCallback(() => clicked++)
  return <>
    {clicked}
    <button onclick={inc}>click me</button>
  </>
}

Parameters

  • fn function (...args: Array<any>): void Any function to wrap with the hook

Returns any The callback function

trigger

src/render.ts:543-559

Triggers a rerender on a hook.

let hook
const Foo = () => {
  hook = current.hook
  return <p>{content}</p>
}
render(<Foo />, c)
trigger(hook)

Parameters

  • hook VHook The hook to trigger

VHook

src/render.ts:18-23

A hook that enables reactive programming. It can be obtained using the export current.hook from inside a functional component and triggered using trigger(hook).

current

src/render.ts:520-526

The current singleton.

Type: Current

hook

src/render.ts:525-525

Holds a reference to a hook that can be triggered later using trigger.

h

src/h.ts:103-107

The virtual node JSX factory. Returns the tree of the node and its children.

const vNode = h('p', { align: 'center' }, ['hello', 'world'])

Parameters

  • type any The element type of the virtual node to be constructed.
  • props any? A props object with arbitrary values.
  • children ...any A VNode.

Returns VNode

Fragment

src/h.ts:90-90

Fragment symbol for JSX fragments <></>.

FunctionalComponent

src/h.ts:83-85

Functional component interface.

const vNode = h(() => ({ type: 'p', props: null, children: ['hello'] }))

Parameters

  • props The properties passed to the component

Returns any The computed VNode.

VNode

src/h.ts:67-71

A virtual dom node.

VType

src/h.ts:52-52

The VNode type.

Type: (FunctionalComponent | CustomElementConstructor | string | symbol)

VProps

src/h.ts:57-57

VNode propeties.

Type: (Record<string, any> | null | undefined)

VChild

src/h.ts:62-62

A VNode child.

Type: (VNode | string | number | boolean | undefined)

Recipes

Getting a reference to an element when it is created inside the component:

const Component = () => {
  const ref = {
    set current(el) {
      // el is now the div below
      // here we can attach event listeners,
      // mutation observers etc.
    },
  }
  return <div ref={ref}></div>
}

Contribute

Fork or edit and submit a PR.

All contributions are welcome!

License

MIT © 2021 stagas