Open-Source Wikis

/

Solid

/

Packages

/

babel-preset-solid

solidjs/solid

babel-preset-solid

Active contributors: Ryan Carniato

Solid's compiler half. The published babel-preset-solid is a 35-line file that wires up babel-plugin-jsx-dom-expressions with Solid-friendly defaults so consumers can drop a single preset name into their Babel config and get the full JSX transform.

Purpose

Solid's runtime advantage — fine-grained reactive DOM updates without a virtual DOM — depends on the JSX you write being rewritten into direct calls into the runtime. babel-preset-solid is the published entry point that performs that rewrite, configured for Solid's specific runtime module names and built-in components.

The actual transform work happens inside babel-plugin-jsx-dom-expressions, declared as a runtime dependency of this preset.

Directory layout

packages/babel-preset-solid/
├── package.json                # peerDependencies, runtime deps, test script
├── README.md                   # config recipes
├── CHANGELOG.md
├── index.js                    # the preset (35 lines)
└── test.js                     # runs babel.transformSync on a tiny snippet

Key abstractions

Symbol Source Description
Default export packages/babel-preset-solid/index.js A function (context, options = {}) that returns { plugins: [[jsxTransform, mergedOptions]] }.
Default options merged into babel-plugin-jsx-dom-expressions packages/babel-preset-solid/index.js moduleName: "solid-js/web", builtIns: ["For", "Show", "Switch", "Match", "Suspense", "SuspenseList", "Portal", "Index", "Dynamic", "ErrorBoundary"], contextToCustomElements: true, wrapConditionals: true, generate: "dom".

How it works

const jsxTransform = require('babel-plugin-jsx-dom-expressions');

module.exports = function (context, options = {}) {
  const plugins = [
    [
      jsxTransform,
      Object.assign(
        {
          moduleName: 'solid-js/web',
          builtIns: [
            'For',
            'Show',
            'Switch',
            'Match',
            'Suspense',
            'SuspenseList',
            'Portal',
            'Index',
            'Dynamic',
            'ErrorBoundary',
          ],
          contextToCustomElements: true,
          wrapConditionals: true,
          generate: 'dom',
        },
        options
      ),
    ],
  ];
  return { plugins };
};

Every option is overridable. The most common reasons to override:

Option Effect Typical value
generate Selects compile target "dom" (default), "ssr", "hydratable", "universal"
hydratable Inserts hydration markers in the output true for SSR + client builds that share data
moduleName Where compiled code imports primitives from "solid-js/web" (default) or your custom renderer module
builtIns Names that get auto-imported instead of looked up by reference Add "YourCustomFlow" if you ship one
contextToCustomElements Walks Solid contexts through Custom Element shadow boundaries true (default)

The README at packages/babel-preset-solid/README.md shows the standard recipes:

// .babelrc — DOM
{ "presets": ["solid"] }

// SSR build
{ "presets": [["solid", { "generate": "ssr", "hydratable": true }]] }

// Client of an SSR app
{ "presets": [["solid", { "generate": "dom", "hydratable": true }]] }

What the transform produces

packages/babel-preset-solid/test.js is a one-shot snapshot test that pins down the public output:

const { code } = babel.transformSync('const v = <div a b={2} />;', {
  presets: [preset],
  babelrc: false,
  compact: true,
});

assert.equal(
  code,
  'import{template as _$template}from"solid-js/web";var _tmpl$=/*#__PURE__*/_$template(`<div a b=2>`);const v=_tmpl$();'
);

Three things to notice in the output:

  1. JSX becomes a _$template call carrying a static HTML fragment.
  2. Imports come from moduleName (solid-js/web).
  3. _$template(...) is annotated /*#__PURE__*/ so bundlers can drop the call when its result is unused.

For non-trivial expressions, the transform also emits _$insert(_el$, () => ...) calls for reactive children, _$delegateEvents([...]) for event delegation, and _$spread(...) for spread attributes — all runtime helpers exported from solid-js/web.

graph LR
    JSX[Source JSX] --> Babel[babel-plugin-jsx-dom-expressions]
    Babel -->|template strings| Tmpl["_$template(...)"]
    Babel -->|reactive bindings| Insert["_$insert(...)"]
    Babel -->|spreads| Spread["_$spread(...)"]
    Babel -->|delegated events| Delegate["_$delegateEvents(...)"]
    Tmpl --> Web[solid-js/web]
    Insert --> Web
    Spread --> Web
    Delegate --> Web

Key source files

File Purpose
packages/babel-preset-solid/index.js The full preset implementation.
packages/babel-preset-solid/test.js The snapshot test. Run with pnpm --filter babel-preset-solid test.
packages/babel-preset-solid/package.json Declares babel-plugin-jsx-dom-expressions as a dep and solid-js/@babel/core as peers.
packages/babel-preset-solid/README.md Config recipes.

Integration points

  • The default moduleName: "solid-js/web" is what makes solid-js/web the canonical compile target.
  • builtIns is the link between the preset and the components and control flow page. When a new flow tag is added to solid-js, it should be added to this list so the compiler auto-imports it.
  • The plugin lives in the sibling dom-expressions repository. Both Solid and the plugin are versioned together so that the runtime imports the plugin emits actually exist in the runtime version you ship.
  • Used by vite-plugin-solid (workspace devDep), rollup-preset-solid (community), and the packages/solid-ssr examples (packages/solid-ssr/examples/*/rollup.config.js).

Entry points for modification

  • Adding a new built-in: append to the builtIns array. Keep it in sync with packages/solid/src/render/index.ts's public exports.
  • Bumping the plugin: update the babel-plugin-jsx-dom-expressions dependency. The Update dom-expressions packages to ... commits in git log show the recurring cadence — the plugin and the runtime version in solid-js are bumped together.
  • Changing default options: any change here is breaking for downstream consumers. Add a major-version changeset (pnpm bump) and document the migration path in the changeset notes.

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

babel-preset-solid – Solid wiki | Factory