What Immer Does
- produce — take state + recipe, return new state
- Structural sharing — only changed paths are copied
- Freeze — returned state is deeply frozen in dev
- Patches — capture the diff for undo/redo or sync
- Curried produce —
produce(recipe)returns a reducer - setAutoFreeze — disable freezing in production for speed
- castDraft / castImmutable — TypeScript helpers
Architecture
Proxy-based draft: when you access or modify the draft, Immer lazily clones the touched path and tracks mutations. On commit, a new tree is built. Untouched subtrees are shared (structural sharing), so the new state is memory-efficient.
Self-Hosting
Library ships with your app.
Key Features
- Write mutating code, get immutable result
- Structural sharing (memory efficient)
- Deep freezing in dev
- Patch-based diffs (undo/redo)
- Curried produce for reducers
- TypeScript types
- Tiny (~3KB gzipped)
- Used by Redux Toolkit, Zustand, Valtio
Comparison
| Approach | Syntax | Memory | Type Safety |
|---|---|---|---|
| Immer | Mutating draft | Structural sharing | Yes |
| Manual spread | Verbose | Manual | Yes |
| Immutable.js | Own types | OK | Wrapped types |
| Seamless-immutable | Light | OK | Limited |
| Mori | Clojure-like | Persistent | Limited |
常见问题 FAQ
Q: 性能开销? A: Proxy 有少量开销,但结构共享节省内存。大部分应用感受不到。Hot path 可以关 autoFreeze。
Q: 和 Redux 关系?
A: Redux Toolkit 的 createSlice 内部用 Immer。这就是为什么你在 reducer 里可以直接 state.value += 1。
Q: 支持 Map/Set 吗?
A: 支持。需要 enableMapSet()。v10+ 默认启用常见 ES 集合类型。
来源与致谢 Sources
- Docs: https://immerjs.github.io/immer
- GitHub: https://github.com/immerjs/immer
- License: MIT