0.0.1 • Published 6 months ago

@fredgig/solid-js-universal v0.0.1

Weekly downloads
-
License
ISC
Repository
-
Last release
6 months ago

Solid Universal

This contains the means to create the runtime for a custom renderer for Solid. This can enable using Solid to render to different platforms like native mobile and desktop, canvas or WebGL, or even the terminal. It relies on custom compilation from babel-preset-solid and exporting the result of createRenderer at a referenceable location.

Example

Babel

To use a custom renderer available in the (fictional) solid-custom-dom package you'd configure your babelrc as:

{
  "presets": [
    [
      "babel-preset-solid",
      {
        "moduleName": "solid-custom-dom",
        "generate": "universal"
      }
    ]
  ]
}

Vite

To use a custom renderer available in the (fictional) solid-custom-dom package you'd configure your vite config as:

import { defineConfig } from 'vite';
import solidPlugin from 'vite-plugin-solid';

export default defineConfig({
  plugins: [solidPlugin({
    solid: {
      moduleName: "solid-custom-dom",
      generate: 'universal'
    }
  })]
});

To create a custom renderer you must implement certain methods and export (as named exports) the results. You may also want to forward solid-js control flow to allow them to be auto imported as well.

// example custom dom renderer
import { createRenderer } from "solid-js/universal";

const PROPERTIES = new Set(["className", "textContent"]);

export const {
  render,
  effect,
  memo,
  createComponent,
  createElement,
  createTextNode,
  insertNode,
  insert,
  spread,
  setProp,
  mergeProps,
  use
} = createRenderer({
  createElement(string) {
    return document.createElement(string);
  },
  createTextNode(value) {
    return document.createTextNode(value);
  },
  replaceText(textNode, value) {
    textNode.data = value;
  },
  setProperty(node, name, value) {
    if (name === "style") Object.assign(node.style, value);
    else if (name.startsWith("on")) node[name.toLowerCase()] = value;
    else if (PROPERTIES.has(name)) node[name] = value;
    else node.setAttribute(name, value);
  },
  insertNode(parent, node, anchor) {
    parent.insertBefore(node, anchor);
  },
  isTextNode(node) {
    return node.type === 3;
  },
  removeNode(parent, node) {
    parent.removeChild(node);
  },
  getParentNode(node) {
    return node.parentNode;
  },
  getFirstChild(node) {
    return node.firstChild;
  },
  getNextSibling(node) {
    return node.nextSibling;
  }
});

// Forward Solid control flow
export {
  For,
  Show,
  Suspense,
  SuspenseList,
  Switch,
  Match,
  Index,
  ErrorBoundary
} from "solid-js";

Then to consume:

import { render } from "solid-custom-dom";

function App() {
  // the skies the limits
}

render(() => <App />, mountNode)

Note: For TypeScript support of non-standard JSX you will need to provide your own types at a jsx-runtime entry on your package so that it can be set as the jsxImportSource. If mixing and matching different JSX implementations you will need use the per file pragmas.

0.0.1

6 months ago