immer
11.2.9 · 22 Oct 2026MIT89.4M / weekRepositoryHomepagenpmAtom feed
193 stable releases, newest first, by release line. Notes are quoted as the maintainers published them.
- 11.x · latest line
11.2.9
22 Oct 2026Export WritableNonArrayDraft from immer.ts so it gets picked up by type generation in builds
11.2.8
22 Oct 2026Skip patches of a draft discarded by writing its base value back
11.2.7
21 Oct 2026Snapshot array length before optimized filter callbacks
11.2.6
21 Oct 2026Avoid excessive Draft recursion for readonly arrays in recursive types
11.2.4
21 Oct 2026Resolve the splice start index against the pre-splice length in array-methods plugin
11.2.3
20 Oct 2026Skip nested patches for children of shifted or reordered arrays
11.2.2
20 Oct 2026Export WritableNonArrayDraft type.
11.2.1
20 Oct 2026Rebuild Set snapshots without mutating the traversal
11.2.0
20 Oct 2026utils: add isModified helper to check whether a draft was modified
11.1.23
20 Oct 2026Preserve live Map iteration during draft mutations
11.1.22
20 Oct 2026Snapshot the iteration range of array searches
11.1.21
2 Oct 2026Throw on reads of a revoked Map or Set draft
11.1.20
2 Oct 2026Do not record a deletion when a base value is written back
11.1.19
2 Oct 2026Forward thisArg in the array-methods plugin
11.1.17
16 Aug 2026Preserve structural sharing for no-op array-methods calls
11.1.16
5 Aug 2026Key inserted array indices by name in the array-methods plugin
11.1.14
16 Jul 2026Throw proper immer error when applyPatches path traverses null
11.1.13
16 Jul 2026Draft relocated base refs after reverse/sort in array-methods plugin
11.1.10
3 Jul 2026Undefined assigned to a prototype-inherited key gets dropped
11.1.9
1 Jul 2026- security
Prevent prototype pollution via constructor.prototype access (CVE-2026-XXXX)
11.1.8
8 May 2026Update current and original typings to assert draft value is unwrapped
11.1.7
6 May 2026Improve higher order type inference for WritableDraft
11.1.6
4 May 2026Remove invalid curried producer type
11.1.5
4 May 2026Handle nested proxies after spreading and inserting into an array
11.1.4
10 Feb 2026Handle nested proxies after spreading and inserting into an array
11.1.3
29 Dec 2025Recursive T for WritableDraft
11.1.2
29 Dec 2025Bogus commit to retest release
11.1.0
20 Dec 2025Mutating:
push,pop,shift,unshift,splice,reverse,sortNon-mutating:
filter,slice,concat,flat,find,findIndex,findLast,findLastIndex,some,every,indexOf,lastIndexOf,includes,join,toString,toLocaleStringOverride array methods to avoid proxy creation while iterating and updating
This feature release adds a new optional "array method overrides" plugin that significantly speeds up array methods when accessing drafts.
Changelog
Performance Improvements
As part of the recent performance optimization work, our benchmarks showed that all Proxy-based immutable update libraries were drastically slower than vanilla JS when calling both mutating and non-mutating array methods. After investigation, it turns out that an array method like
arr.filter()causes the Proxy'sgettrap to trigger for every single item in the array. This in turn forces creation of a new Proxy and internal Immer metadata for every item, even though this was just a read operation and no items were being updated.This release adds a new
enableArrayMethodsplugin that will override draft array methods to bypass the draft and directly operate on the underlying wrapped array instance. This significantly speeds up array operations.When enabled, the plugin overrides these array methods:
Mutating:
push,pop,shift,unshift,splice,reverse,sortNon-mutating:
filter,slice,concat,flat,find,findIndex,findLast,findLastIndex,some,every,indexOf,lastIndexOf,includes,join,toString,toLocaleString
Our benchmarks show that the overridden methods (plus the other perf changes in Immer 10.2 and 11.0) are 50-80% faster than the baseline behavior of Immer 10.1.
The plugin adds about 1.5-2K minified to Immer's bundle size.
It's important to note that the plugin does change the "safe to mutate a draft" semantics of Immer. Any of these methods that receives an array item as a callback argument will not automatically wrap that item in a Proxy!. That means that if you try to mutate an argument in a method such as
filter, it will actually mutate the real underlying object, which will cause bugs in your app. This is an intentional design tradeoff. Semantically, all of these methods imply read-only access to array values, so if your code tries to mutate an array item in a callback, that is a bug in your code.Note that this does not override
map,flatMap,forEach, orreduce/reduceRight. Those methods do imply either side effects and potential mutations, or returning arbitrary values. Given that, we determined it was both safest and simplest to keep their behavior as-is.See the Array Methods Plugin docs page for further details on the behavior of the overridden methods.
What's Changed
Override array methods to avoid proxy creation while iterating and updating
11.0.0
23 Nov 2025- breaking
Enable loose iteration by default
- breaking
Simplify some iteration checks
- breaking
Allow passing type to get/set utils to skip archetype lookup
Performance Improvements
Rewrite finalization system to use a callback approach instead of tree traversal
Breaking changes
- breaking
Enable loose iteration by default
- breaking
Simplify some iteration checks
- breaking
Allow passing type to get/set utils to skip archetype lookup
- breaking
Convert assigned_ to Map
- breaking
Enable loose iteration
- breaking
Replace recursive tree finalization with targeted callbacks
Ported Mutative's "finalization callback" approach as a more targeted and performant implementation for finalization compared to the existing recursive tree traversal approach:
- breaking
Added cleanup callbacks for each draft that's created
- breaking
Added callbacks to handle root drafts, assigned values, and recursing
inside of plain values - breaking
Updated state creation to return [draft, state] to avoid a lookup
- breaking
Rewrote patch generation system to work with callbacks instead of
during tree traversal
- breaking
Update self-reference test with new behavior
- breaking
Apply code review suggestions
- breaking
Byte-shave scopes and patch plugin usage
- breaking
Inline finalizeAssigned
- breaking
Move fixPotentialSetContents to plugin
- breaking
Byte-shave typeof utils
- breaking
Byte-shave Object references
- breaking
Byte-shave field names and arrow functions
- 10.x
10.2.0
25 Oct 2025Optimize Immer performance where possible, introduce
setUseStrictIteration
10.1.3
1 Sep 2025Mark exports as pure, for better tree-shakability
10.1.2
1 Sep 2025non-enumerable (immutable) methods on Map/Set
Update package.json exports for react-native
10.1.1
27 Apr 2024Export lost types
Make
applyPatchesto acceptreadonly Patch
10.1.0
27 Apr 2024performance: Make non-strict mode faster for classes. Addresses #1071 (53e3203). Immer 10.x solved slow iteration for plain JS objects. This update applies the same handling to class instances. In cases this makes class instance handling 3 times faster. Note that this slightly modifies the behavior of Immer with classes in obscure corner cases, in ways that match current documentation, but do not match previous behavior. If you run into issues with this release icmw. class instances, use
setUseStrictShallowCopy("class_only")to revert to the old behavior. For more details see immerjs.github.io/immer/complex-objects
10.0.2
9 May 2023Export
ObjectishtypeMove index.js.flow from dist/ -> dist/cjs/ to match index.js
10.0.0
17 Apr 2023- breaking
Immer 10 only supports modern browsers, that have support for
Proxy,Reflect,SymbolandMapandSet. - breaking
There is no longer a UMD build exposed (thanks Mark Erikson for modernizing the build setup in #1032!
Release notes
- breaking
Immer 10 only supports modern browsers, that have support for
Proxy,Reflect,SymbolandMapandSet. - breaking
There is no longer a UMD build exposed (thanks Mark Erikson for modernizing the build setup in #1032!
- breaking
Getters and setters are ignored by default on plain object, as this is a very uncommon case and provides a significant performance boost (ca 33%, but depends a lot on the scenario). Fixes #867, #1012. Thanks hrsh7th for implementing it in #941!
- breaking
Promise based reducers are no longer supported. Conceptually it is an anti pattern to hold on to drafts over time. If needed the old behavior can still be achieved by leveraging
createDraftandfinishDraft. - breaking
ES5 mode (for legacy browsers) has been dropped. If your project relies on
enableES5(), you SHOULD NOT upgrade Immer.enableES5has been removed. - breaking
produceis no longer exposed as thedefaultexport. This improves eco system compatibility, and makes sure that there is only one correct way of doing things - breaking
enableAllPluginshas been removed, useenablePatches(); enableMapSet()instead - breaking
Shortening the length of a JSON array now results in delete patches, rather than a mutation of the
lengthproperty, in accordance with JSON spec. Thanks kshramt for implementing this in #964! Immer is now an ESM package that can be directly imported into the browser. CJS should still work, UMD support has been removed.
Overall, there is a rough performance increase of 33% for Immer (and in some cases significantly higher), and the (non gzipped) bundle size has reduced from 16 to 11.5 KB, while the the minimal gzipped import of just
producehas remained roughly the same at 3.3 KB.For more details, see #1015
Migration steps
If you have any
enableES5()call, don't migrateWhen using getters/ setters icmw plain objects, call
useStrictShallowCopy(true)at startupReplace all default imports: Replace
import produce from "immer"withimport {produce} from "immer"Replace all calls to
enableAllPlugins()withenablePatches(); enableMapSet();to be more specific and smoothen future migrations.If any producer returned a Promise, refactor it to leverage
createDraftinstead. Roughly:
const newState = await produce(oldState, recipe) // becomes const draft = createDraft(oldState) await recipe(draft) const newState = finishDraft(draft)
- 9.x
9.0.21
23 Mar 2023Ensure type exports is first in package.json export declaration
9.0.20
23 Mar 2023Patching maps failed when using number keys
9.0.19
27 Jan 2023Don't freeze drafts returned from produce if they were passed in as draft
Produce results should never be frozen when returned from nested produces, to prevent 'hiding' drafts. Fixes #935
Release and publish from 'main' rather than 'master' branch
Bug Fixes
Don't freeze drafts returned from produce if they were passed in as draft
Produce results should never be frozen when returned from nested produces, to prevent 'hiding' drafts. Fixes #935
Release and publish from 'main' rather than 'master' branch
Revert earlier fix (#990) for recursive types
Upgrade Github actions to Node 16 attempt 1
Upgrade Github actions to Node 16 attempt 2
9.0.17
2 Jan 2023Special case NaN in setter