# fre

> Tiny Concurrent UI library with Fiber.

Latest version **2.8.9** (published 2026-06-08) · MIT license · 0 weekly downloads

## Install

```sh
npm install fre
pnpm add fre
yarn add fre
bun add fre
```

## Health

**Score 65/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 2.8.9 |
| Published | 2026-06-08 |
| First published | 2018-07-28 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 158 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 3764 |
| Author | 132yse |
| Maintainers | yse |
| Keywords | fre, frontend, framework, vdom, concurrent-mode, fiber, web, ui-library |

## Links

- npm: https://www.npmjs.com/package/fre
- Repository: https://github.com/yisar/fre
- Homepage: https://fre.js.org
- Issues: https://github.com/yisar/fre/issues
- npm.io page: https://npm.io/package/fre

## Alternatives

- [@opentelemetry/exporter-zipkin](https://npm.io/package/@opentelemetry/exporter-zipkin.md) — 14.8M weekly downloads
- [pusher-js](https://npm.io/package/pusher-js.md) — 2.0M weekly downloads
- [browserify](https://npm.io/package/browserify.md) — 1.7M weekly downloads
- [sqs-consumer](https://npm.io/package/sqs-consumer.md) — 1.7M weekly downloads
- [@sanity/eventsource](https://npm.io/package/@sanity/eventsource.md) — 930.8K weekly downloads

## Recent versions

- 2.8.9 (latest) — 2026-06-08
- 2.8.8 — 2025-09-17
- 2.8.7 — 2025-09-09
- 2.8.6-fix6 — 2025-09-09
- 2.8.6-fix5 — 2025-09-09
- 2.8.6-fix4 — 2025-09-09
- 2.8.6-fix3 — 2025-09-08
- 2.8.6-fix2 — 2025-09-08
- 2.8.6-fix1 — 2025-09-08
- 2.8.6 — 2025-09-08
- 2.8.5 — 2025-09-08
- 2.8.4 — 2025-09-05
- 2.8.3 — 2025-08-05
- 2.8.2 — 2025-08-01
- 2.8.1 — 2025-07-24
- … 217 more at https://npm.io/package/fre/versions

## README

<div align="center">

<p><img src="https://user-images.githubusercontent.com/44045911/147237798-174728c9-7399-4b47-be39-78ef69198a0d.png" alt="fre logo" width="130"></p>
<h1>Fre</h1>
<p>👻 Tiny Concurrent UI library with Fiber.</p>

![GitHub License](https://img.shields.io/github/license/frejs/fre)
[![Build Status](https://img.shields.io/github/actions/workflow/status/yisar/fre/main.yml)](https://github.com/yisar/fre/actions)
[![Code Coverage](https://img.shields.io/codecov/c/github/frejs/fre.svg)](https://codecov.io/gh/yisar/fre)
[![npm-v](https://img.shields.io/npm/v/fre.svg)](https://npmjs.com/package/fre)
[![npm-d](https://img.shields.io/npm/dt/fre.svg)](https://npmjs.com/package/fre)
[![brotli](http://img.badgesize.io/https://unpkg.com/fre/dist/fre.js?compression=brotli&label=brotli)](https://bundlephobia.com/result?p=fre)

</div>


- **Concurrent Mode** — This is an amazing idea, which implements the coroutine scheduler in JavaScript, it also called **Time slicing**.

- **Keyed reconcilation algorithm** — Fre has a minimal diff algorithm, It supported keyed, pre-process, offscreen rendering and SSR hydration.

- **Do more with less** — Fre get the tiny size, but it has most features, virtual DOM, hooks API, Suspense, Fragments, Fre.memo and so on.

### Contributors

<a href="https://github.com/yisar/fre/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=yisar/fre" />
</a>

### Usage

https://deepwiki.com/frejs/fre

```shell
yarn add fre
```

```js
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)
```
### Features

- [Suspense](https://github.com/yisar/fre#Suspense)

- [memo](https://github.com/yisar/fre#memo)

- [ErrorBoundary](https://github.com/yisar/fre#ErrorBoundary)

### Hooks API

- [useState](https://github.com/yisar/fre#usestate)

- [useEffect](https://github.com/yisar/fre#useeffect)

- [useReducer](https://github.com/yisar/fre#usereducer)

- [useLayout](https://github.com/yisar/fre#uselayout)

- [useCallback](https://github.com/yisar/fre#usecallback)

- [useMemo](https://github.com/yisar/fre#usememo)

- [useRef](https://github.com/yisar/fre#useref)

- [useContext](https://github.com/yisar/fre#useContext)


#### 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

```js
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

```js
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
```

```js
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:

```js
useEffect(() => {
  document.title = 'count is ' + count
  return () => {
    store.unsubscribe()
  }
}, [])
```

#### useLayout

More like useEffect, but useLayout is sync and blocking UI.

```js
useLayout(() => {
  document.title = 'count is ' + count
}, [flag])
```

#### useMemo

`useMemo` has the same rules as `useEffect`, but `useMemo` will return a cached value.

```js
const memo = (c) => (props) => useMemo(() => c, [Object.values(props)])
```

#### useCallback

`useCallback` is based `useMemo`, it will return a cached function.

```js
const cb = useCallback(() => {
  console.log('cb was cached.')
}, [])
```

#### useRef

`useRef` will return a function or an object.

```js
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.

```js
function App() {
  const t = useRef((dom) => {
    if (dom) {
      doSomething()
    } else {
      cleanUp()
    }
  })
  return flag && <span ref={t}>I will removed</span>
}
```

#### useContext

```js
import { createContext, useContext } from 'react';

const ThemeContext = createContext(null);

function App() {
  return (
    <ThemeContext value="dark">
      <Button />
    </ThemeContext>
  )
}

function Button({ children }) {
  const theme = useContext(ThemeContext);
  const className = 'button-' + theme;
  return (
    <button class={className}>
      {children}
    </button>
  );
}
```

### Suspense
```js
const Hello = lazy('./hello.js')

export function App() {
  return (
    <div>
      <Suspense fallback={<div>loading...</div>}>
        <Hello />
        <div>world!</div>
      </Suspense>
    </div>
  )
}
```

### ErrorBoundary
```js
function A(){
  throw new Error('render error test')
}

export function App() {
  return (
    <div>
      <ErrorBoundary fallback={<div>occur an error</div>}>
        <A />
      </ErrorBoundary>
    </div>
  )
}
```

### Fragments

```js
// fragment
function App() {
  return <>{something}</>
}
// render array
function App() {
  return [a, b, c]
}
```


### jsx

For vite example

```js
export default {
  esbuild: {
    jsxFactory: 'h',
    jsxFragment: 'Fragment',
    jsxInject: `import { h, Fragment } from 'fre'`,
    target: 'es2020',
    format: 'esm'
  }
}
```

#### License

MIT @yisar


[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fyisar%2Ffre.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fyisar%2Ffre?ref=badge_large)

---
_Source: https://npm.io/package/fre · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
