stellis
TypeScript icon, indicating that this package has built-in type declarations

0.1.2 • Public • Published

stellis

A no-VDOM, JSX framework for SSR

NPM JavaScript Style Guide

Install

npm install --save stellis
yarn add stellis
pnpm add stellis

Setup for classic JSX

Comment pragmas (Babel, Typescript, ESBuild etc.)

  • Automatic runtime

    /* @jsxRuntime automatic */
    /* @jsxImportSource stellis */
  • Classic runtime

    /* @jsxRuntime classic */
    /* @jsx h */
    /* @jsxFrag Fragment */
    import { h, Fragment } from 'stellis';

Typescript

Reference: https://www.typescriptlang.org/docs/handbook/jsx.html#configuring-jsx

  • Automatic runtime

    {
      "compilerOptions": {
        "jsx": "react-jsx", // or "react-jsxdev"
        "jsxImportSource": "stellis",
      }
    }
  • Classic runtime

    {
      "compilerOptions": {
        "jsx": "react",
        "jsxFactory": "h",
        "jsxFragmentFactory": "Fragment"
      }
    }
import { h, Fragment } from 'stellis';

ESBuild

Reference: https://esbuild.github.io/api/#transformation

  • Automatic runtime

    • CLI

      esbuild --jsx=automatic --jsx-import-source="stellis" --jsx-dev
    • Options

      const option = {
        jsx: 'automatic',
        jsxDev: true | false,
        jsxImportSource: 'stellis',
      };
  • Classic runtime (as options)

    • CLI

      esbuild --jsx=transform --jsx-factory=h --jsx-fragment=Fragment
    • Options

      const option = {
        jsx: 'transform',
        jsxFactory: 'h',
        jsxFragment: 'Fragment',
      };

Setup for optimized JSX

Babel

Stellis uses Babel to transform your JSX and is provided in the form a plugin exported through stellis/babel.

Integrations

  • Rollup (SOON)
  • Vite (SOON)
  • ESBuild (SOON)

Usage

Rendering JSX

import { render } from 'stellis';

const result = await render(<h1>Hello World</h1>);
console.log(result); // <h1>Hello World</h1>

Stellis JSX is unlike your usual, React-like JSX:

  • Stellis has no VDOM
    • The babel compiler will always generate optimized templates from the JSX
  • Stellis' attributes are closer to HTML
    • React introduced some properties like className, htmlFor and readOnly to be closer to DOM than HTML, which is the opposite of Stellis, where you can write class, html and readonly.
  • Rendering is always async

Writing your first component

function Message({ greeting, receiver }) {
  return <h1>{greeting}, {receiver}</h1>;
}

const result = await render(
  <Message greeting="Hello" receiver="World" />
); // <h1>Hello World</h1>

Async components

async function Profile({ id }) {
  const user = await getUser(id);

  return <ProfileDetails user={user} />;
} 
async function Profile({ id }) {
  return <ProfileDetails user={await getUser(id)} />;
} 

Attributes

class and class:<name> directives

<h1 class="example">Hello</h1>
<h1 class={["a", condB && b]}>Array</h1>
<h1 class={{ a: true, b: condB, c: condC }}>Object</h1>
<h1 class={["a", { b: condB }, [condC && "c"]]}>Nested</h1>
<h1 class:example>Hello</h1>
<h1 class:a class:b={cond}>Another Example</h1>

style and style:<property> directives

<h1 style={{color: "red"}}>Red Heading</h1>
<h1 style:color="red">Red Heading 2</h1>

set:html

Sets the raw HTML content of the given element. Always takes priority over children.

<div set:html="<script>Hello World</script>" />

Built-in Components

ErrorBoundary/<stellis:boundary>

Attempts to render children. If it receives an error, fallback is called with the received error and the result is rendered instead.

import { ErrorBoundary, render } from 'stellis';

function FailingComponent() {
  throw new Error('Example');
}

const result = await render(
  <ErrorBoundary
    fallback={(error) => <>
      <h1>Error: {error.name}</h1>
      <p>Message: {error.message}</p>
    </>}
  >
    <FailingComponent />
  </ErrorBoundary>
);
console.log(result);
// Output: <h1>Error: Error</h1><p>Message: Example</p>

Fragment/<stellis:fragment>

Same behavior as <></> except this allows raw HTML output with set:html

<Fragment set:html="<script>Hello World</script>" />
<stellis:fragment set:html="<script>Hello World</script>" />

Comment/<stellis:comment>

Allow inserting HTML comments

<stellis:comment value="This is a comment." />
// Output: <!--This is a comment.-->

Dynamic

import { Dynamic, render } from 'stellis';

function Example({ as, children }) {
  return <Dynamic component={as}>{children}</Dynamic>;
}

const result = await render(
  <Example as="h1">Hello World</Example>
);
console.log(result);
// Output: <h1>Hello World</h1>

Context API

import { createContext, setContext, getContext, render } from 'stellis';

const message = createContext('Hello World');

function Parent({ children }) {
  setContext(message, 'Bonjour World');

  return children;
}

function Child() {
  return <h1>{getContext(message)}</h1>; // Hello World
}

const result = await render(
  <>
    <Parent>
      <Child />
    </Parent>
    <Child />
  </>
);

console.log(result);

// Output
// <h1>Bonjour World</h1><h1>Hello World</h1>

Stellis meta

Built-in components that renders after the markup has resolved. Both <stellis:head> and <stellis:body> has the types "pre" and "post" which defines where the children are going to be injected.

Head/<stellis:head>

<stellis:head type="pre">
  <title>Hello World</title>
</stellis:head>

Body/<stellis:body>

<stellis:body type="post">
  <script src="./my-script.js" />
</stellis:body>

Sponsors

Sponsors

License

MIT © lxsmnsyc

Readme

Keywords

Package Sidebar

Install

npm i stellis

Weekly Downloads

0

Version

0.1.2

License

MIT

Unpacked Size

556 kB

Total Files

44

Last publish

Collaborators

  • lxsmnsyc