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

@viceser/view

v0.0.1

Published

A high-performance, lightweight virtual DOM library with efficient diffing and patching algorithms. Built for modern web applications with JSX support, server-side rendering, and minimal overhead.

Readme

@viceser/view

A high-performance, lightweight virtual DOM library with efficient diffing and patching algorithms. Built for modern web applications with JSX support, server-side rendering, and minimal overhead.

✨ Features

  • 🚀 Ultra-fast DOM patching - Minimal DOM operations through intelligent diffing
  • ⚛️ JSX Support - Full JSX/TSX compatibility with custom runtime
  • 🔄 Efficient Diffing - Smart tree comparison with cache key optimization
  • 🌐 Universal Rendering - Server-side and client-side rendering support
  • 🎯 Tiny Bundle Size - Minimal footprint without sacrificing features
  • 🔧 TypeScript First - Full type safety and excellent IntelliSense
  • 🎪 Fragment Support - Built-in Fragment component for grouping elements
  • 🎨 Modern Event Handling - Efficient event delegation and management

📦 Installation

npm install @viceser/view

📦 Bundle Options

This library provides multiple build options optimized for different environments and use cases:

Module Formats

Default Import (Environment-aware)

import { h, patchFactory } from '@viceser/view';
// Automatically resolves to browser or server build based on environment

Browser Bundles (Optimized for Performance)

For optimal browser performance, the library provides pre-bundled versions:

<!-- Development Bundle (24.9kb) - Human readable, includes source maps -->
<script type="module">
  import { h, patchFactory } from './node_modules/@viceser/view/dist/client.bundle.js';
</script>

<!-- Production Bundle (10.0kb) - Minified for maximum performance -->
<script type="module">
  import { h, patchFactory } from './node_modules/@viceser/view/dist/client.bundle.min.js';
</script>

Direct Bundle Import

// Import specific bundle version
import { h, patchFactory } from '@viceser/view/bundle';
// Always resolves to production minified bundle (10.0kb)

Server Support (Node.js Compatible)

For server-side rendering and Node.js environments:

// CommonJS (traditional Node.js) - uses bundled version
const { h, htmlFactory, buildRoot } = require('@viceser/view/server');

// ES Modules (modern Node.js) - uses TypeScript-compiled modular version
import { h, htmlFactory, buildRoot } from '@viceser/view/server';

Build Commands

To generate the latest bundles, run:

npm run build            # Build everything: TypeScript + client bundles + server CommonJS bundle
npm run build:tsc        # Build only TypeScript (includes server ESM)
npm run build:bundle     # Build only client bundles (dev + prod)
npm run build:server:cjs # Build only server CommonJS bundle

Bundle Comparison

| Format | Size | Use Case | Source Maps | |--------|------|----------|-------------| | Default Client | 368B | Node.js import, bundler usage | ✅ | | Development Bundle | 24.9kb | Browser development, debugging | ✅ | | Production Bundle | 10.0kb | Browser production, performance | ✅ | | Server ESM (TypeScript) | 310B + deps | Modern Node.js with ES modules | ✅ | | Server CommonJS Bundle | 14.6kb | Traditional Node.js with require() | ✅ |

When to Use Each Bundle

  • Default Import: Use with modern bundlers (Vite, Webpack, etc.) for automatic optimization
  • Development Bundle: Use for browser development when debugging without a bundler
  • Production Bundle: Use for maximum performance in browsers without a bundler (60% smaller)
  • Server ESM (TypeScript): Use in modern Node.js environments - modular, efficient, relies on compiled dependencies
  • Server CommonJS Bundle: Use in traditional Node.js environments or when needing a single self-contained file

🚀 Quick Start

Basic Usage

Option 1: Dynamic Patching (Simplified API)

import { h, patchFactory } from '@viceser/view';

// Set up patch function with just the target element
const element = document.getElementById('app');
const patch = patchFactory(element);

// Start with some content
patch(
  h(
    'div',
    { class: 'container' },
    h('h1', null, 'Hello World'),
    h('p', null, 'This is a paragraph'),
  ),
);

// Update with new content dynamically
patch(
  h(
    'div',
    { class: 'container updated' },
    h('h1', null, 'Hello Universe'),
    h('p', null, 'This is an updated paragraph'),
    h('button', { onClick: () => console.log('clicked') }, 'Click me'),
  ),
);

Option 2: Pre-initialized Patching (Traditional API)

import { h, patchFactory } from '@viceser/view';

// Create initial virtual DOM
const initialVNode = h(
  'div',
  { class: 'container' },
  h('h1', null, 'Hello World'),
  h('p', null, 'This is a paragraph'),
);

// Set up patch function with initial state and target element
const element = document.getElementById('app');
const patch = patchFactory(initialVNode, element);

// Render initial content immediately
patch();

// Update with new virtual DOM
const updatedVNode = h(
  'div',
  { class: 'container updated' },
  h('h1', null, 'Hello Universe'),
  h('p', null, 'This is an updated paragraph'),
  h('button', { onClick: () => console.log('clicked') }, 'Click me'),
);

// Apply the update
patch(updatedVNode);

JSX Setup

Configure your tsconfig.json for JSX:

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "@viceser/view"
  }
}

Then use JSX naturally:

import { Fragment } from '@viceser/view/jsx-runtime';

function App({ name }: { name: string }) {
  return (
    <div className="app">
      <h1>Welcome, {name}!</h1>
      <Fragment>
        <p>This is a fragment</p>
        <p>Multiple elements without wrapper</p>
      </Fragment>
    </div>
  );
}

🏗️ Core Concepts

Virtual DOM Nodes (Patches)

Virtual DOM nodes are represented as patches with the following structure:

interface Patch {
  a?: Action; // Action type (Add, Change, Move, Delete, Swap)
  i?: number; // Index position
  t?: PatchTag; // Tag name or component
  c?: PatchChildren[]; // Children
  at?: PatchAttributes; // Attributes
  v?: string | null; // Text value
  m?: number; // Move target index
  ns?: string; // Namespace (for SVG)
  k?: string; // Key for reconciliation
  ck?: unknown; // Cache key for optimization
}

Actions

The library supports five core actions:

  • A - Add: Create new DOM node
  • C - Change: Update existing node
  • M - Move: Reposition node
  • D - Delete: Remove node
  • S - Swap: Exchange positions of two nodes

Patch Factory

The patchFactory creates a patching function that handles diffing and DOM updates automatically:

import { patchFactory } from '@viceser/view';

const patch = patchFactory(targetElement);
// Returns a function that can be called with new virtual DOM to update

When to Use Each Signature

Use patchFactory(node) when:

  • Building dynamic UIs with changing content
  • Working with state management libraries
  • Creating reusable components that render different content
  • Starting with an empty container

Use patchFactory(initialPatch, node) when:

  • You have a predefined initial layout
  • Building static sites with occasional updates
  • Server-side rendering with client-side hydration
  • You want to separate initial render from updates
// Dynamic content example
const dynamicPatch = patchFactory(document.getElementById('dynamic'));
dynamicPatch(userGeneratedContent);

// Pre-initialized example
const staticPatch = patchFactory(<Layout />, document.getElementById('static'));
staticPatch(); // Renders Layout immediately

📚 API Reference

Core Functions

h(tag, attributes, ...children)

Creates virtual DOM nodes (equivalent to React.createElement):

// Element nodes
const div = h('div', { id: 'app', className: 'container' }, 'Hello');

// Component nodes
const MyComponent = (props) => h('span', null, props.text);
const comp = h(MyComponent, { text: 'Hello Component' });

// With JSX
const jsx = (
  <div id="app" className="container">
    Hello
  </div>
);

patchFactory(node) or patchFactory(initialPatch, node)

Creates a patching function for efficient DOM updates. Supports two signatures for different use cases:

Signature 1: Dynamic Patching (Recommended for most use cases)

import { patchFactory } from '@viceser/view';

// Set up with just the target element
const patch = patchFactory(document.getElementById('app'));

// Apply patches dynamically
patch(<div>First content</div>);
patch(<div>Updated content</div>);
patch(); // Clears content (renders undefined)

Signature 2: Pre-initialized Patching (Great when you have initial content)

import { patchFactory } from '@viceser/view';

// Set up with initial virtual DOM and target element
const patch = patchFactory(<div>Initial content</div>, document.getElementById('app'));

// Render initial content
patch();

// Update to new content
patch(<div>Updated content</div>);

// For document-level updates
const docPatch = patchFactory(<html><body>Initial</body></html>, document);
docPatch(); // Renders initial content to document
docPatch(<html><body>Updated</body></html>); // Updates html, head, and body elements

htmlFactory(patch)

Renders virtual DOM to HTML string (server-side):

import { htmlFactory } from '@viceser/view';

const html = htmlFactory(vnode);
// Returns HTML string representation

Environment-Specific Exports

This library provides different builds optimized for client and server environments:

Client-Side (Browser) Exports

Default import automatically resolves to client build in browser environments:

import {
  h,              // createElement function
  Fragment,       // Fragment component
  patchFactory,   // Creates DOM patch function (client-only)
  htmlFactory,    // Renders to HTML string
  diffFactory,    // Creates diff computation function
  domPatch,       // Direct DOM patching utilities (client-only)
  Children,       // Type for component children
} from '@viceser/view';

// Client-specific functions for DOM manipulation
const patch = patchFactory(document.getElementById('app'));
patch(<div>Hello Browser!</div>);

// Direct DOM operations
domPatch(element, patches);

Server-Side (Node.js) Exports

In Node.js environments, the library automatically provides server-optimized build:

// Automatic server build in Node.js
import {
  h,              // createElement function
  Fragment,       // Fragment component
  htmlFactory,    // Renders to HTML string
  buildRoot,      // Build root element (server-only)
  diffFactory,    // Creates diff computation function
  Children,       // Type for component children
} from '@viceser/view';

function App({ title }) {
  return (
    <html>
      <head>
        <title>{title}</title>
      </head>
      <body>
        <div id="app">
          <h1>Server Rendered!</h1>
        </div>
      </body>
    </html>
  );
}

// Server-specific HTML generation
const html = htmlFactory(<App title="My App" />);
const rootElement = buildRoot(html);

Explicit Import Paths

You can also import from specific builds explicitly:

// Force client build
import { patchFactory, domPatch } from '@viceser/view/client';

// Force server build
import { buildRoot } from '@viceser/view/server';

Shared API

These functions are available in both environments:

  • h - createElement function
  • Fragment - Fragment component
  • htmlFactory - Renders to HTML string
  • diffFactory - Creates diff computation function
  • Children - Type for component children

JSX Runtime

The JSX runtime is automatically imported when using JSX:

// These are available from @viceser/view/jsx-runtime
import { jsx, jsxs, Fragment } from '@viceser/view/jsx-runtime';

// But you typically don't import these directly - they're used automatically

📚 Advanced Features

Fragment Component

Use fragments to group elements without wrapper:

import { Fragment } from '@viceser/view/jsx-runtime';

function List() {
  return (
    <Fragment>
      <li>Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
    </Fragment>
  );
}

// Or with JSX shorthand
function List() {
  return (
    <>
      <li>Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
    </>
  );
}

Cache Keys for Optimization

Use cache keys to skip expensive computations:

function ExpensiveComponent({ data }) {
  return <div cache:key={data.id}>{/* Expensive rendering logic */}</div>;
}

Namespaces for SVG

Proper SVG support with namespaces:

function Icon() {
  return (
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
      <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />
    </svg>
  );
}

Event Handling

Efficient event handling with automatic delegation:

function Button({ onClick, children }) {
  return (
    <button
      onClick={onClick}
      onMouseEnter={(e) => console.log('hover')}
      onCapture:Focus={(e) => console.log('focus captured')}
    >
      {children}
    </button>
  );
}

Refs

Access DOM elements directly:

function Input() {
  const handleRef = (element) => {
    if (element) {
      element.focus();
    }
  };

  return <input ref={handleRef} type="text" />;
}

Style Objects

Dynamic styling with object notation:

function StyledDiv({ color, size }) {
  return (
    <div
      style={{
        backgroundColor: color,
        fontSize: `${size}px`,
        padding: '10px',
        borderRadius: '4px',
      }}
    >
      Styled content
    </div>
  );
}

Diff Factory for Optimization

Use diffFactory to create efficient state-aware diffing:

import { diffFactory } from '@viceser/view';

// Create a diff function for a specific component
function useOptimizedUpdates(initialState) {
  const renderState = (state) => (
    <div className="counter">
      <span>Count: {state.count}</span>
      <button disabled={state.loading}>
        {state.loading ? 'Loading...' : 'Click me'}
      </button>
    </div>
  );

  const diff = diffFactory(renderState(initialState));

  return (newState) => {
    return diff(renderState(newState)); // Returns minimal patch
  };
}

// Usage
const updateCounter = useOptimizedUpdates({ count: 0, loading: false });
const patch = updateCounter({ count: 1, loading: false }); // Only updates count

🔧 Integration Examples

With State Management

import { h, patchFactory } from '@viceser/view';

class SimpleStore {
  constructor(initialState) {
    this.state = initialState;
    this.listeners = [];
  }

  setState(newState) {
    this.state = { ...this.state, ...newState };
    this.listeners.forEach((listener) => listener(this.state));
  }

  subscribe(listener) {
    this.listeners.push(listener);
    return () => {
      this.listeners = this.listeners.filter((l) => l !== listener);
    };
  }
}

const store = new SimpleStore({ count: 0 });

function Counter({ count }) {
  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={() => store.setState({ count: count + 1 })}>
        Increment
      </button>
    </div>
  );
}

// Method 1: Simplified API (Recommended)
const patch = patchFactory(document.getElementById('app'));

// Render initial state
patch(<Counter count={store.state.count} />);

// Subscribe to state changes
store.subscribe((state) => {
  patch(<Counter count={state.count} />);
});

// Method 2: Traditional API (Alternative)
const initialVNode = <Counter count={store.state.count} />;
const patchTraditional = patchFactory(
  initialVNode,
  document.getElementById('app2'),
);

patchTraditional(); // Render initial
store.subscribe((state) => {
  patchTraditional(<Counter count={state.count} />);
});

Server-Side Rendering

// server.ts
import { htmlFactory } from '@viceser/view';

function App({ title }) {
  return (
    <html>
      <head>
        <title>{title}</title>
      </head>
      <body>
        <div id="app">
          <h1>Server Rendered!</h1>
        </div>
      </body>
    </html>
  );
}

const html = htmlFactory(<App title="My App" />);

Diff Factory for State Management

import { diffFactory, h } from '@viceser/view';

// Create a diff factory with initial state
const initialPatch = <div>Loading...</div>;
const createDiff = diffFactory(initialPatch);

// Use it to track state changes
function useStateDiff(initialState) {
  const stateDiff = diffFactory(renderState(initialState));

  return function updateState(newState) {
    const newPatch = renderState(newState);
    return stateDiff(newPatch); // Returns only the differences
  };
}

// Example usage
function renderState(state) {
  return (
    <div className="app">
      <h1>Count: {state.count}</h1>
      <button disabled={state.loading}>
        {state.loading ? 'Loading...' : 'Increment'}
      </button>
      <ul>
        {state.items.map((item, i) => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  );
}

const stateDiff = useStateDiff({ count: 0, loading: false, items: [] });

// Each call returns only the patch for what changed
const patch1 = stateDiff({ count: 1, loading: false, items: [] });
// Only updates count

const patch2 = stateDiff({ count: 1, loading: true, items: [] });
// Only updates button state

const patch3 = stateDiff({
  count: 1,
  loading: false,
  items: [{ id: 1, name: 'New Item' }]
});
// Only updates loading state and list

⚡ Performance Tips

1. Choose the Right patchFactory Signature

// ✅ Use simplified API for dynamic content
const patch = patchFactory(element);
patch(dynamicContent); // More flexible, cleaner code

// ✅ Use traditional API when you have predefined initial content
const patch = patchFactory(initialContent, element);
patch(); // Immediate render of initial content

2. Use Keys for List Items

function TodoList({ todos }) {
  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>{todo.text}</li>
      ))}
    </ul>
  );
}

3. Leverage Cache Keys

function ExpensiveList({ items, filter }) {
  const filteredItems = useMemo(
    () => items.filter((item) => item.type === filter),
    [items, filter],
  );

  return (
    <div cache:key={filter}>
      {filteredItems.map((item) => (
        <Item key={item.id} {...item} />
      ))}
    </div>
  );
}

4. Reuse Patch Functions

// Create one patch function per element/container
const patch = patchFactory(element);

// Reuse it for all updates - very efficient!
patch(content1);
patch(content2);
patch(content3);

// Don't create new patch functions unnecessarily
// ❌ Inefficient
content.forEach((item) => {
  const itemPatch = patchFactory(containerElement); // Creates new function each time
  itemPatch(item);
});

// ✅ Efficient
const patch = patchFactory(containerElement);
content.forEach((item) => {
  patch(item); // Reuses same patch function
});

🛠️ TypeScript Support

Full TypeScript definitions included:

import type {
  Patch,
  PatchAttributes,
  PatchChildren,
  Action,
} from '@viceser/view';

// Custom component with proper typing
interface ButtonProps {
  variant?: 'primary' | 'secondary';
  onClick?: (event: MouseEvent) => void;
  children: PatchChildren;
}

function Button({
  variant = 'primary',
  onClick,
  children,
}: ButtonProps): Patch {
  return (
    <button className={`btn btn-${variant}`} onClick={onClick}>
      {children}
    </button>
  );
}

🤝 Contributing

Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.

📄 License

MIT License - see the LICENSE file for details.

🔗 Links


Built with ❤️ for modern web development

📦 What's Exported

Client-side Build

// Default import in browser environments
import {
  h,
  Fragment,
  patchFactory,
  htmlFactory,
  diffFactory,
  domPatch,
  Children,
} from '@viceser/view';

// Or explicit client import
import {
  h,
  Fragment,
  patchFactory,
  htmlFactory,
  diffFactory,
  domPatch,
  Children,
} from '@viceser/view/client';

Server-side Build

// Default import in Node.js environments
import {
  h,
  Fragment,
  htmlFactory,
  buildRoot,
  diffFactory,
  Children,
} from '@viceser/view';

// Or explicit server import
import {
  h,
  Fragment,
  htmlFactory,
  buildRoot,
  diffFactory,
  Children,
} from '@viceser/view/server';

JSX Runtime

// Automatically imported by JSX transform
import { jsx, jsxs, Fragment } from '@viceser/view/jsx-runtime';

// Manual imports for utilities
import {
  encodeEntities,
  jsxEscape,
  jsxAttr,
  jsxTemplate,
} from '@viceser/view/jsx-runtime';

Key Differences

| Function | Client | Server | Purpose | | -------------- | ------ | ------ | --------------------------------- | | h | ✅ | ✅ | createElement function | | Fragment | ✅ | ✅ | Fragment component | | htmlFactory | ✅ | ✅ | Renders to HTML string | | diffFactory | ✅ | ✅ | Creates diff computation function | | Children | ✅ | ✅ | Type for component children | | patchFactory | ✅ | ❌ | DOM patching (requires DOM) | | domPatch | ✅ | ❌ | Direct DOM operations |

| buildRoot | ❌ | ✅ | Build root element |

🔧 JSX Runtime

@viceser/view provides a complete JSX runtime with automatic transforms and manual utilities:

Automatic JSX Transform

Configure your tsconfig.json or build tool:

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "@viceser/view"
  }
}

Your JSX is automatically transformed:

// Your JSX
const App = () => (
  <div className="app">
    <h1>Hello World</h1>
    <button onClick={handleClick}>Click me</button>
  </div>
);

// Becomes (automatic transform)
import { jsx as _jsx } from '@viceser/view/jsx-runtime';
const App = () =>
  _jsx('div', {
    className: 'app',
    children: [
      _jsx('h1', { children: ['Hello World'] }),
      _jsx('button', { onClick: handleClick, children: ['Click me'] }),
    ],
  });

Manual JSX Runtime

For advanced use cases or server-side rendering:

import {
  jsx,
  Fragment,
  encodeEntities,
  jsxAttr,
} from '@viceser/view/jsx-runtime';

// Manual JSX creation
const element = jsx('div', {
  className: 'container',
  children: [
    jsx('h1', { children: ['Safe Content'] }),
    jsx('p', { children: [encodeEntities('User & Input <script>')] }),
  ],
});

// Custom attribute handling
const styleAttr = jsxAttr('style', {
  color: 'red',
  fontSize: 16,
  backgroundColor: 'blue',
});
// Returns: 'style="color:red;font-size:16px;background-color:blue;"'

// HTML entity encoding
const safeText = encodeEntities('<script>alert("xss")</script>');
// Returns: '&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;'

Template Literals (Experimental)

For precompiled template optimization:

import { jsxTemplate } from '@viceser/view/jsx-runtime';

const template = jsxTemplate`
  <div class="user">
    <h2>${'name'}</h2>
    <p>Score: ${'score'}</p>
  </div>
`;