Skip to content

Latest commit

 

History

History
199 lines (151 loc) · 5.67 KB

prax_readme.md

File metadata and controls

199 lines (151 loc) · 5.67 KB

Overview

prax.mjs provides a very simple and performant system for rendering DOM/XML/HTML. It was originally React-inspired, but semantics are much simpler and more universally useful.

Isomorphic SSR is supported via lightweight and performant dom_shim. Pairing these modules together, and using custom DOM elements, provides a good foundation for hybrid SSR/SPA.

Short overview of features:

  • Directly create DOM nodes.
    • No string templates.
    • No VDOM.
    • Can instantiate with new.
  • Convenient syntax. Nice-to-use in plain JS.
    • No templates.
    • No string parsing.
    • No need for JSX.
    • No need for a build system.
  • Render only once. Use native custom elements for state.
    • Use dom_reg for more convenient element registration.
  • Good for SSR/SPA hybrids.

Complemented by:

TOC

Usage

Rendering is done via Ren. You must create an instance, which should be a singleton. You can also subclass Ren and override individual methods to customize its behavior.

Browser example:

import * as p from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/prax.mjs'
import {A} from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/prax.mjs'

const ren = new p.Ren()
const E = ren.elemHtml.bind(ren)

const elem = E(`div`, {id: `main`, class: `outer`},
  E(`p`, {class: `inner`},
    `hello `,
    `world!`,
  ),
)

document.body.append(elem)

/*
The following elements (not strings) have been appended:

<div id="main" class="outer"><p class="inner">hello world!</p></div>
*/

For rendering to string, use .outerHTML:

console.log(elem.outerHTML)

/*
<div id="main" class="outer"><p class="inner">hello world!</p></div>
*/

Usage with custom elements:

import * as p from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/prax.mjs'
import * as dr from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/dom_reg.mjs'

const ren = new p.Ren()
const E = ren.elemHtml.bind(ren)

class SomeLink extends dr.MixReg(HTMLAnchorElement) {
  init(href, text) {
    return E(this, {href, class: `link`}, text)
  }
}

document.body.append(
  new SomeLink().init(`/some-path`, `click me!`),
)

SSR

For SSR (server-side rendering), Prax needs our lightweight DOM shim:

import * as p from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/prax.mjs'
import * as dg from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/dom_global_shim.mjs'

const ren = new p.Ren(dg.global.document)
const E = ren.elemHtml.bind(ren)

const elem = E(`div`, {id: `main`, class: `outer`},
  E(`p`, {class: `inner`}, `hello world!`),
)

console.log(elem.outerHTML)

/*
<div id="main" class="outer"><p class="inner">hello world!</p></div>
*/

For SSR/SPA hybrids, configure an importmap or bundler to choose the right global document and pass it to Ren. The rest will just work.

import * as p from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/prax.mjs'

// Your bundler or importmap should choose the right one.
import * as dg from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/dom_global_shim.mjs'
import * as dg from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/dom_global_native.mjs'

const ren = new p.Ren(dg.global.document)
const E = ren.elemHtml.bind(ren)

// In both environments, this will be a DOM element.
// In SSR, it will be shimmed.
const elem = E(`div`, {id: `main`, class: `outer`},
  E(`p`, {class: `inner`}, `hello world!`),
)

Rendering a complete document with doctype:

import * as p from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/prax.mjs'
import * as dg from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/dom_global_shim.mjs'

const ren = new p.Ren(dg.global.document)
const E = ren.elemHtml.bind(ren)

const elem = E(`html`, {lang: `en`},
  E(`head`, null,
    E(`link`, {rel: `stylesheet`, href: `/styles/main.css`}),
    E(`title`, null, `page title`),
  ),
  E(`body`, null,
    E(`main`, {class: `main`}, `hello world!`),
  ),
)

console.log(p.DOCTYPE_HTML + elem.outerHTML)

/*
Formatted here for viewing convenience:

<!doctype html>
<html lang="en">
  <head>
    <link rel="stylesheet" href="/styles/main.css" />
    <title>page title</title>
  </head>
  <body>
    <main class="main">hello world!</main>
  </body>
</html>
*/

API

Undocumented

The following APIs are exported but undocumented. Check prax.mjs.