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 automatic element registration.
- Use
- Good for SSR/SPA hybrids.
Complemented by:
dom_shim
for SSR.dom_reg
for automatically registering custom elements.obs_dom
for making custom elements automatically react to observables.
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/js@0.1.53/prax.mjs'
import {A} from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.53/prax.mjs'
const ren = p.Ren.native()
const {E} = ren
document.body.append(
E.div.props(A.id(`main`).cls(`outer`)).chi(
E.p.props(A.cls(`inner`)).chi(
`hello `,
`world!`,
),
),
)
/*
The following elements (not strings) have been appended:
<div id="main" class="outer">
<p class="inner">hello world!</p>
</div>
*/
For string rendering, use .outerHTML
:
import * as p from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.53/prax.mjs'
import {A} from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.53/prax.mjs'
const ren = p.Ren.native()
const {E} = ren
// Note the `.outerHTML` call at the end.
console.log(
E.div.props(A.id(`main`).cls(`outer`)).chi(
E.p.props(A.cls(`inner`)).chi(
`hello `,
`world!`,
),
).outerHTML,
)
/*
<div id="main" class="outer">
<p class="inner">hello world!</p>
</div>
*/
Usage with custom elements. The methods .props
and .chi
are provided by patching the prototype of the given base element class, which is entirely opt-in.
import * as p from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.53/prax.mjs'
import {A} from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.53/prax.mjs'
import * as dr from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.53/dom_reg.mjs'
const ren = p.Ren.native()
class SomeLink extends dr.MixReg(HTMLAnchorElement) {
init(href, text) {
return this
.props(A.href(href).cls(`link`))
.chi(text)
}
}
document.body.append(
new SomeLink().init(`/some-path`, `click me!`),
)
For SSR/SPA hybrids, configure an importmap or bundler to choose the right "dom globals" for the right environment, and pass those globals to the Ren
you're instantiating. The rest will just work.
import * as p from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.53/prax.mjs'
// Choose the right one.
import * as dg from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.53/dom_glob_shim.mjs'
import * as dg from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.53/dom_glob_native.mjs'
const ren = p.Ren.from(dg.glob)
Rendering a complete document with doctype:
import * as p from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.53/prax.mjs'
import * as dg from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.53/dom_glob_shim.mjs'
const ren = p.Ren.from(dg.glob)
const {E} = ren
const A = p.PropBui.main
console.log(p.renderDocument(
E.html.props(A.lang(`en`)).chi(
E.head.chi(
E.link.props(A.rel(`stylesheet`).href(`/styles/main.css`)),
E.title.chi(`page title`),
),
E.body.chi(
E.main.props(A.cls(`main`)).chi(
`hello world!`,
),
),
),
))
/*
<!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>
*/
The following APIs are exported but undocumented. Check prax.mjs.
const nsHtml
const nsSvg
const nsMathMl
const BOOL
const VOID
class Ren
class Raw
class RenPh
class RenHtmlPh
class RenSvgPh
class RenFunPh
class RenFunHtmlPh
class RenFunSvgPh
class MixRenCache
class PropBui
function renderDocument
function isSeq
function isNodable
function reqNodable
function isRaw
function reqRaw
function isNode
function reqNode
function isElement
function reqElement
function isDocument
function optDocument
function reqDocument
function isNamespaced
function deref