Skip to content

feat(joint-react): server-side rendering + new @joint/svg-shim package#3343

Open
samuelgja wants to merge 3 commits into
clientIO:devfrom
samuelgja:feat/joint-react+shimpackage
Open

feat(joint-react): server-side rendering + new @joint/svg-shim package#3343
samuelgja wants to merge 3 commits into
clientIO:devfrom
samuelgja:feat/joint-react+shimpackage

Conversation

@samuelgja
Copy link
Copy Markdown
Contributor

@samuelgja samuelgja commented Jun 2, 2026

Description

Adds server-side rendering for JointJS and a new reusable package that makes it possible.

New package: @joint/svg-shim

A headless DOM + SVG-geometry shim so @joint/core's Vectorizer / dia.Paper runs in Node, with no browser. It plugs exactly the holes a headless DOM leaves:

  • Installs a headless DOM (jsdom by default; happy-dom or a custom window factory also supported).
  • Polyfills the missing SVG geometrygetBBox, SVGMatrix/SVGPoint/SVGTransform, transform lists, font-size coercion, HTMLImageElement.
  • Measures text with the real font via the bundled @napi-rs/canvas, so server-measured labels match the browser pixel-for-pixel.

Production-ready: ESM/CJS/types build, Jest tests, shared @joint/eslint-config, README, .gitignore. Exports ., ./install (side-effect entry), and a client-safe ./flag subpath (zero Node imports) so the browser bundle never pulls the Node-only shim. It is reusable by both @joint/core (pure) and @joint/react via an injectable text-style resolver.

@joint/react server rendering

import '@joint/react/server' installs the shim and registers a server paper renderer, so a plain <GraphProvider><Paper renderElement={…}/></GraphProvider> rendered with renderToString emits the full diagram SVG inline, which then hydrates into the live, interactive paper on the client. jsdom/@napi-rs/canvas moved to optional peers on @joint/svg-shim, so client-only consumers install nothing extra.

Examples (packages/joint-svg-shim/examples)

  • react-ssr — Vite + Express: server-render the interactive diagram, ship it as SVG, hydrate on the client. Styled. Works with JavaScript disabled.
  • core-static — pure @joint/core: build a diagram in Node, serialize with paper.svg.outerHTML, serve as static HTML. No React, no client JS.

Motivation and Context

JointJS builds diagrams from real SVG DOM and measures geometry through it (getBBox, matrices, text width). In Node there is no DOM, and even a headless DOM implements no SVG layout — so a server-rendered paper collapses (labels lose size, links lose geometry). @joint/svg-shim makes server rendering work and correct, unlocking SEO-friendly first paint, emailable diagrams, and @joint/react SSR + hydration. The shim is isolated as its own package so @joint/core can reuse it later without depending on React.

Screenshots (if appropriate):

@joint/core on the server — pure @joint/core + @joint/svg-shim: the diagram is built in Node, serialized with paper.svg.outerHTML, and shipped as static SVG in the HTML. No browser, no client JavaScript, not interactive.

Screenshot 2569-06-02 at 17 56 33

@joint/react on the serverrenderToString ships the full diagram as SVG in the HTML (works with JavaScript disabled), then hydrates into the live, interactive JointJS paper on the client.

Screenshot 2569-06-02 at 17 57 20

samuelgja added 3 commits May 30, 2026 18:49
…g across various examples

- Updated Paper component style properties to use single quotes for consistency.
- Replaced usePaperEvents with direct event handlers for onLinkMouseEnter, onLinkMouseLeave, onElementMouseEnter, and onElementMouseLeave in multiple examples.
- Added eslint-disable comments for performance-related rules in several files.
- Cleaned up unused imports and improved code readability in various components.
… removed redundant code blocks and optimized function calls.
@samuelgja samuelgja requested a review from kumilingus June 2, 2026 10:58
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.

1 participant