npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

light-jsx

v0.6.8

Published

Light implementation of JSX, that produces DOM nodes and allows for reactivity.

Downloads

63

Readme

Light JSX · GitHub license · npm version · bundle size · typescript used

Light JSX is a simple JavaScript library for creating reactive websites. It doesn't use any behind scene magic, like Virtual DOM or compilation, to render your apps, all JSX translated directly to nodes and updates them when state of your app changes.

  • No compilation step. Your app doesn't need any additional compilation steps. Typescript will do everything needed.
  • Light. Package size is 2 times less than other popular JSX libraries.
  • Native. Every JSX turns into DOM nodes, that makes debugging less painfull.
  • Simple. It's very easy to understand, especially if you used JSX libraries before.
  • Fine grained reactivity. DOM changes only when and where needed.

Instalation

First, install light-jsx.

npm i light-jsx

Then add this lines to your tsconfig.json.

    "jsx": "react",
    "jsxFactory": "LightJSX.DOMcreateElement",
    "jsxFragmentFactory": "LightJSX.Fragment"

And you are ready to start!

Examples

Hello world example

import { LightJSX } from "light-jsx"

// equal to <div>Hello world!</div>, surprising, isn't it?
let hello = <div>Hello world!</div>

LightJSX.render(document.body, hello)

Counter example

import { LightJSX, createSignal } from "light-jsx"

// creating state
// val = Getter<number>
// setVal = Setter<number>
const [val, setVal] = createSignal(0)

// changing state on click and displaying it
let counter = <button onclick={() => setVal((c) => c + 1)}>Count: {val}</button>

LightJSX.render(document.body, counter)

Computed example

import { LightJSX, createComputed, createSignal } from "light-jsx"

// creating state
// val = Getter<number>
// setVal = Setter<number>
const [val, setVal] = createSignal(0)

// creating computed
const double = createComputed(() => val() * 2)

// changing state on click and displaying it
let counter = (
    <>
        <button onclick={() => setVal((c) => c + 1)}>Count: {val}</button>
        <div>double: {double}</div>
    </>
)

LightJSX.render(document.body, counter)

Effect example

In this app a() + b() will be equal to sum() in any case

import { LightJSX, createEffect, createSignal } from "light-jsx"

// states
const [a, setA] = createSignal(0)
const [b, setB] = createSignal(0)
const [sum, setSum] = createSignal(0)

// effects
// every time sum or b changes, this code will run
createEffect(() => {
    setA(sum() - b())
})

// every time sum or a changes, this code will run
createEffect(() => {
    setB(sum() - a())
})

// keep in mind, that effects will run once immediately after they setup

// rendering multiple elements using fragment
const app = (
    <>
        <button onclick={() => setA((a) => a + 1)}>{a}</button>
        <span>+</span>
        <button onclick={() => setB((b) => b + 1)}>{b}</button>
        <span>=</span>
        <button onclick={() => setSum((sum) => sum + 1)}>{sum}</button>
    </>
)

LightJSX.render(document.body, app)

Function components

import { LightJSX, createEffect, createSignal } from "light-jsx"

// function component with props type declaration
// also keep in mind, that it will be called once per component
function StrangeCalculator(props: { initialSum?: number }) {
    const [a, setA] = createSignal(0)
    const [b, setB] = createSignal(0)
    const [sum, setSum] = createSignal(props.initialSum ?? 0)

    createEffect(() => {
        setA(sum() - b())
    })

    createEffect(() => {
        setB(sum() - a())
    })

    // styles
    return (
        <div style={{ "padding": "6px" }}>
            <button onclick={() => setA((a) => a + 1)}>{a}</button>
            <span>+</span>
            <button onclick={() => setB((b) => b + 1)}>{b}</button>
            <span>=</span>
            <button onclick={() => setSum((sum) => sum + 1)}>{sum}</button>
        </div>
    )
}

// rendering multiple components won't break anything
LightJSX.render(document.body, <StrangeCalculator initialSum={10} />)
LightJSX.render(document.body, <StrangeCalculator />)
LightJSX.render(document.body, <StrangeCalculator initialSum={100} />)

How it works

As you might point out getter is function, but when passing it as JSX child we don't call it. Every function passed as JSX child is considered state dependand and will be rerendered every time signals used inside it changes.

This code will log every time val is changed, because getVal is dependand on it.

import { LightJSX, createSignal } from "light-jsx"

const [val, setVal] = createSignal(0)

const getVal = () => {
    console.log("getting value: ", val())
    return val()
}

let counter = <button onclick={() => setVal((c) => c + 1)}>Count: {getVal}</button>

LightJSX.render(document.body, counter)

Based on this you may already guessed how poor use of library would look.

Bad code examples. Don't repeat it at home.

// this won't update at all, because there are no function
// functions is the key for reactivity
let badCounter1 = <button onclick={() => setVal((c) => c + 1)}>Count: {val()}</button>

// this will update
// but instead of rendering element once, it will rerender everything every time val changes
let badCounter2 = () => <button onclick={() => setVal((c) => c + 1)}>Count: {val()}</button>

let double = () => val() * 2
// this code will compute double 8 times
// instead you can use createComputed, that will run calculations once
let overlyExaggeratedExample = (
    <div>
        {double} {double} {double} {double} {double} {double} {double} {double}
    </div>
)

Happy coding!