Open-Source Wikis

/

Solid

/

Packages

/

solid-js/h and solid-js/html

solidjs/solid

solid-js/h and solid-js/html

Active contributors: Ryan Carniato

Two compiler-free entry points for using Solid without JSX or a build step. solid-js/h exposes a HyperScript factory; solid-js/html exposes a tagged-template literal. Both produce the same DOM the JSX compiler would, at the cost of a slightly larger runtime that cannot be tree-shaken.

Purpose

The default story for Solid is JSX + babel-preset-solid. These two entries cover the cases where that is not available:

  • Running Solid in a <script> tag with no build (CDN usage, REPLs).
  • Embedding in environments that already standardise on a non-JSX templating shape (htm, lit-html style).
  • Authors who simply prefer not to use JSX.

Both packages are thin wrappers — the bulk of the work is done in the hyper-dom-expressions and lit-dom-expressions sibling libraries.

Directory layout

packages/solid/
├── h/
│   ├── package.json            # ./h export selector
│   ├── tsconfig.json
│   ├── README.md               # API + caveats
│   └── src/
│       ├── index.ts            # createHyperScript wiring
│       └── hyperscript.ts      # imported types from hyper-dom-expressions
└── html/
    ├── package.json            # ./html export selector
    ├── tsconfig.json
    ├── README.md
    └── src/
        ├── index.ts            # createHTML wiring
        └── lit.ts              # imported types from lit-dom-expressions

packages/solid/h/jsx-runtime/   # JSX runtime entry for HyperScript-backed JSX
└── src/
    └── index.ts

The h/jsx-runtime/ entry is what enables "jsxImportSource": "solid-js/h" in tsconfig.json for projects that want to use TypeScript's JSX with HyperScript output (for example, Solid in a non-Babel pipeline).

Key abstractions

solid-js/h

Symbol Source Description
h(tag, props?, ...children) packages/solid/h/src/index.ts The HyperScript factory. Three call shapes: element name + props + children, element name + children, component + props/children.
HyperScript (type) hyper-dom-expressions (re-exported via hyperscript.ts) The functional surface of h.

Implementation:

import {
  assign,
  createComponent,
  dynamicProperty,
  insert,
  spread,
  SVGElements,
} from 'solid-js/web';
import { createHyperScript } from './hyperscript.js';

const h: HyperScript = createHyperScript({
  spread,
  assign,
  insert,
  createComponent,
  dynamicProperty,
  SVGElements,
});
export default h;

createHyperScript (from hyper-dom-expressions) accepts the runtime primitive bag and returns the h factory. The actual element-creation logic lives there.

solid-js/html

Symbol Source Description
html`<button>${count}</button>` packages/solid/html/src/index.ts The tagged-template literal. ${} interpolates JS expressions; <//> closes a component.
HTMLTag (type) lit-dom-expressions (re-exported via lit.ts) The signature of the html literal.

Implementation:

import { createHTML } from "./lit.js";
import {
  effect, style, insert, untrack, spread, createComponent, delegateEvents,
  classList, dynamicProperty, mergeProps, setAttribute, setAttributeNS,
  addEventListener, Aliases, getPropAlias, Properties, ChildProperties,
  DelegatedEvents, SVGElements, SVGNamespace
} from "solid-js/web";

const html: HTMLTag = createHTML({ effect, style, insert, ... });
export default html;

Both factories take their primitives from solid-js/web (which itself re-exports them from dom-expressions). They depend on solid-js/web only — not on solid-js's reactive runtime directly.

How they differ from JSX

The READMEs at packages/solid/h/README.md and packages/solid/html/README.md enumerate the gotchas. Summary:

Concern JSX h / html
Reactive expressions Compiler wraps automatically Must be wrapped in () => ... manually
Spreading props <div {...props} /> h("div", mergeProps({class: "foo"}, props)) or template-literal ...${props}
Refs ref={el => ...} or let myEl; <div ref={myEl} /> Only the callback form is supported
Fragments <>...</> Plain arrays in h; multiple top-level elements work natively in html
Bundle size Tree-shakeable runtime Pulls in hyper-dom-expressions / lit-dom-expressions runtime, not tree-shakeable

Key source files

File Purpose
packages/solid/h/src/index.ts Wires createHyperScript to solid-js/web.
packages/solid/h/src/hyperscript.ts Type re-exports for the HyperScript shape.
packages/solid/h/jsx-runtime/src/index.ts JSX runtime entry — lets TypeScript's JSX transform target solid-js/h directly.
packages/solid/html/src/index.ts Wires createHTML to solid-js/web.
packages/solid/html/src/lit.ts Type re-exports for the HTMLTag shape.

Integration points

  • Both depend on solid-js/web (Rollup external: ["solid-js/web"]).
  • Indirectly depend on hyper-dom-expressions (workspace devDep) and lit-dom-expressions (workspace devDep) — the actual factories live there.
  • Used by the JSX-less playground builds and by solid-element projects that want to author components in a script-tag context.

Entry points for modification

  • Updating to a new hyper-dom-expressions version: bump the workspace devDependency in the root package.json. The Solid-side wiring in packages/solid/h/src/index.ts rarely needs to change because the constructor accepts the runtime bag, not specific behaviours.
  • Adding a new operator (e.g. server-rendered tagged literal): add a parallel entry under packages/solid/html/server/ and wire it up in packages/solid/rollup.config.js. As of today, the tagged literal is browser-only because lit-dom-expressions does not ship a server build.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

solid-js/h and solid-js/html – Solid wiki | Factory