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

    2.4.4 • Public • Published

    fre logo

    Fre

    👻 Tiny Concurrent UI library with Fiber.

    Build Status Code Coverage npm-v npm-d brotli

    • Concurrent Mode — This is an amazing idea, which implements the coroutine scheduler in JavaScript, it also called Time slicing.

    • O(ND) reconcilation algorithm — Fre has a minimal longest-increasing-subsequence algorithm, It supported keyed, pre-process.

    • Do more with less — After tree shaking, project of hello world is only 1KB, but it has most features, virtual DOM, hooks API, Fragments and so on.

    Sponsors

    Contributors

    Use

    yarn add fre
    import { render, useState } from 'fre'
    
    function App() {
      const [count, setCount] = useState(0)
      return <>
          <h1>{count}</h1>
          <button onClick={() => setCount(count + 1)}>+</button>
        </>
    }
    
    render(<App/>, document.body)

    Hooks API

    useState

    useState is a base API, It will receive initial state and return an Array

    You can use it many times, new state is available when component is rerender

    function App() {
      const [up, setUp] = useState(0)
      const [down, setDown] = useState(0)
      return (
        <>
          <h1>{up}</h1>
          <button onClick={() => setUp(up + 1)}>+</button>
          <h1>{down}</h1>
          <button onClick={() => setDown(down - 1)}>-</button>
        </>
      )
    }

    useReducer

    useReducer and useState are almost the same,but useReducer needs a global reducer

    function reducer(state, action) {
      switch (action.type) {
        case 'up':
          return { count: state.count + 1 }
        case 'down':
          return { count: state.count - 1 }
      }
    }
    
    function App() {
      const [state, dispatch] = useReducer(reducer, { count: 1 })
      return (
        <>
          {state.count}
          <button onClick={() => dispatch({ type: 'up' })}>+</button>
          <button onClick={() => dispatch({ type: 'down' })}>-</button>
        </>
      )
    }

    useEffect

    It is the execution and cleanup of effects, which is represented by the second parameter

    useEffect(f)       //  effect (and clean-up) every time
    useEffect(f, [])   //  effect (and clean-up) only once in a component's life
    useEffect(f, [x])  //  effect (and clean-up) when property x changes in a component's life
    
    function App({ flag }) {
      const [count, setCount] = useState(0)
      useEffect(() => {
        document.title = 'count is ' + count
      }, [flag])
      return (
        <>
          <h1>{count}</h1>
          <button onClick={() => setCount(count + 1)}>+</button>
        </>
      )
    }

    If it returns a function, the function can do cleanups:

    useEffect(() => {
      document.title = 'count is ' + count
      return () => {
        store.unsubscribe()
      }
    }, [])

    useLayout

    More like useEffect, but useLayout is sync and blocking UI.

    useLayout(() => {
      document.title = 'count is ' + count
    }, [flag])

    useMemo

    useMemo has the same rules as useEffect, but useMemo will return a cached value.

    const memo = (c) => (props) => useMemo(() => c, [Object.values(props)])

    useCallback

    useCallback is based useMemo, it will return a cached function.

    const cb = useCallback(() => {
      console.log('cb was cached.')
    }, [])

    useRef

    useRef will return a function or an object.

    function App() {
      useEffect(() => {
        console.log(t) // { current:<div>t</div> }
      })
      const t = useRef(null)
      return <div ref={t}>t</div>
    }

    If it uses a function, it can return a cleanup and executes when removed.

    function App() {
      const t = useRef((dom) => {
        if (dom) {
          doSomething()
        } else {
          cleanUp()
        }
      })
      return flag && <span ref={t}>I will removed</span>
    }

    Fragments

    // fragment
    function App() {
      return <>{something}</>
    }
    // render array
    function App() {
      return [a, b, c]
    }

    jsx2

    plugins: [
      [
        '@babel/plugin-transform-react-jsx',
        {
          runtime: 'automatic',
          importSource: 'fre',
        },
      ],
    ]

    Compare with other frameworks

    The comparison is difficult because the roadmap and trade-offs of each framework are different, but we have to do so.

    • react

    React is the source of inspiration for fre. Their implementation and asynchronous rendering are similar. The most amazing thing is concurrent mode, which means that react and fre have the same roadmap -- Exploring concurrent use cases.

    But at the same time, fre has obvious advantages in reconciliation algorithm and bundle size.

    • vue / preact

    To some extent, vue and preact are similar. They have similar synchronous rendering, only the API is different.

    The reconciliation algorithm of fre is similar to vue3, but the biggest difference is that vue/preact do not support concurrent mode, this means that the roadmap is totally different.

    framework concurrent offscreen reconcilation algorithm bundle size
    fre2 ★★★★ 2kb
    react18 ★★ 43kb
    vue3 × x ★★★★★ 33kb
    preactX × x ★★★ 4kb

    License

    MIT @yisar

    FOSSA Status

    Install

    npm i fre

    Homepage

    fre.js.org

    DownloadsWeekly Downloads

    85

    Version

    2.4.4

    License

    MIT

    Unpacked Size

    66 kB

    Total Files

    26

    Last publish

    Collaborators

    • yse