Skip to content

fix(solid): make the package importable under server conditions (SSR build) - #405

Open
nprbst wants to merge 1 commit into
vercel-labs:mainfrom
nprbst:fix/solid-ssr-import
Open

nprbst wants to merge 1 commit into
vercel-labs:mainfrom
nprbst:fix/solid-ssr-import

Conversation

@nprbst

@nprbst nprbst commented Oct 19, 2026 •

Copy link
Copy Markdown

Fixes #375.

Problem

@json-render/solid is compiled only with Solid's DOM output (generate: "dom"). The DOM output hoists every native-element JSX template to module scope (var _tmpl$ = template(...)), e.g. the markup in ConfirmDialog. Under the node, worker and deno conditions, solid-js/web resolves to its server runtime, where template throws "Client-only API called on the server side" and other DOM-only helpers (such as setStyleProperty) are not exported. So the package throws as soon as it is imported on the server, before any component renders:

npm i @json-render/core @json-render/solid solid-js zod
node --input-type=module -e 'import "@json-render/solid"'
# Error: Client-only API called on the server side. ...
# (with solid-js 1.9.11: SyntaxError: ... does not provide an export named 'setStyleProperty')

Bun fails the same way.

Fix

Ship a second build compiled with Solid's SSR output, and select it with the same export conditions solid-js/web uses, so this package always runs against the runtime solid-js/web resolves to:

  • tsup.config.ts: keep the existing DOM build (index, schema, with types) and add an SSR build of src/index.ts as dist/index.server.{mjs,js}. Both builds have the same exports.
  • package.json: the "." export gains worker, browser, deno and node conditions (mirroring solid-js/web). Browser bundlers and jsdom tests keep getting the DOM build; Node, Bun, Vite SSR and edge workers get the SSR build. types, main/module and ./schema are unchanged.
  • build becomes rm -rf dist && tsup, as in packages/next, since the two configs no longer share a clean.

The SSR build is non-hydratable, matching the existing DOM build; hydration is out of scope here.

Tests

packages/solid/src/ssr.test.ts runs the built package in a plain Node child process, because Vitest here resolves with the browser condition and cannot exercise the server path:

  • importing via ESM and via require under Node's default conditions does not throw;
  • renderToString from solid-js/web renders a spec through JSONUIProvider and Renderer.

All three fail on main with the errors above and pass with this change. @types/node is added to the package's devDependencies so the test type-checks.

  • pnpm turbo run build --filter='./packages/*': 30/30
  • pnpm test: 82 files, 1236 tests passed
  • pnpm type-check: 61/61
  • pnpm lint: 14/14

🤖 Generated with Claude Code

…build)

Fixes vercel-labs#375.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

@nprbst is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

@nprbst
nprbst marked this pull request as ready for review October 19, 2026 21:18

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(solid): package import calls a client-only API on the server

1 participant