immerjs / immer

Create the next immutable state by mutating the current one

Home Page:https://immerjs.github.io/immer/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Immer 10 proposals: Drop promises, default export, array.length patches, ES5 mode, and make getter / setter support opt-in

mweststrate opened this issue Β· comments

πŸš€ Feature Proposal

Hi folks,

I've collected a bunch of issues that are together I think worthy of being put in a separate major version:

  • Disable support for getters / setters by default. Support getters and setters on plain object supports a non-idiomatic pattern where objects aren't purely data and can have side effects. Even though in general Immer does handle does correctly (descriptors are copied etc) there is are still 2 issues with it 1) it has a huge performance impact, and 2) side effects might be triggered non-intentionally. Given that getters / setters is an unidiomatic usage of "immutable" data, I'm proposing to make their support opt in. #1012 #867 #941
  • Drop promise based producer support. Immer supports returning a promise from a producer. I don't think I ever saw usage of that in the wild, and it is a bit of an oxymoron as it makes it easy to leak drafts. Since producers should be like enter-write-exit without happening anything in the mean time, and it complicates the code base unnecessarily, I'm proposing to simply drop it.
  • Drop support for ES5 mode. Proxies are now in all major browsers, and legacy support can stay on Immer 9, I think it is now the time to create a smaller (and simpler) Immer package by removing the ES5 fallback.
  • Drop the default export. It is now valid to do both import produce from 'immer' and import {produce} from 'immer'. Since both default exports and offering two ways to achieve exactly the same are anti patterns, and removing simplifies ESM support, I'm proposing to drop the default export. This is quite a breaking change, but on the upside easily handled by a simple search and replace. #937 (comment) / reduxjs/redux-toolkit#3095
  • Don't use array.length assignment in JSON patches. See #964, array.length assignments should not be used to shorten arrays in JSON patches. Since this can both increase payload sizes and affect logic based on patches, saved this for a major bump.
  • Give ESM another try? See #921. Sigh.
  • [ ] Support map/set by default -> avoid control issues like #1022

Notes to self:

  • TS 5
  • verify all error codes still in use
  • clean up old language constructions, iterators etc
  • communicate that Immer now expects Symbol / Map / Set / Proxy to be present in env
  • update size & perf tables
  • chinese translation update
  • errors -> array

cc @markerikson

@mweststrate AWESOME, great to see this! It aligns wonderfully with the work I'm doing on RTK 2.0.

These all sound like pretty good proposals to me. And yeah, both the default export and ESM things seem like things to put into a major.

Actually, looking at Immer's current package.json, it seems like you already technically are using ESM with the "fix" in 9.0.14 by having both exports and module.

Along with the getter/setter stuff, I wonder if there's any other ideas that could be borrowed from https://github.com/giusepperaso/structura.js or https://github.com/unadlib/mutative to help improve perf?

I agree with all points.
About Node ESM, if it's instead of CJS, I'm okay 😜. But you do need to know, that if there is a Node application that uses both cjs and esm, it means that if in esm mode for example there was a call for enableMapSet() it won't affect cjs files if you export it to 2 js files, that all the different is module.exports vs export {…}. So this needs to be done with caution ⚠️

Yeah, fortunately with RTK we don't have anything stateful that way. I know I've read some articles that have tricks for a file that can be used simultaneously with ESM and CJS imports and correctly share state between (ie, the module is only loaded once despite being loaded in two different ways).

@mweststrate : just out of curiosity, what would be your estimate for the amount of work involved and a vague ETA for releasing Immer 10? No rush, just trying to get a sense of how that would tie into RTK 2.0. (Which will take us a while to get done, trust me :) )

@markerikson my current plan is to work on this 2nd half of March and hopefully release early April.

commented

bunchee, it can simplify esm/cjs export bundle, used by swr.

commented

regarding the Drop the default export work: my project uses eslint and i just upgraded from 8.36.0 to 8.37.0 today, and i started seeing a bunch of warnings:

warning  Using exported name 'produce' as identifier for default export  import/no-named-as-default

what's weird is nothing w/ the eslint-plugin-import plugin changed, and i don't see anything related to that rule changing in my updates today (but maybe something w/ the eslint parsing changed which made the new warning show up)? 🀷

all i had to do was change:

import produce from 'immer';

to:

import { produce } from 'immer';

in a global search/replace.

it was easy to fix, but i wanted to give a heads up here!

also: i'm only mentioning here b/c we might want to update the examples/docs as part of the Drop the default export changes. For example:
https://immerjs.github.io/immer/produce

still uses the "default import".

commented

Tried out RTK 2 alpha, which includes Immer 10 under the hood, and noticed that delete obj.prop['some-prop'] now fails if delete obj.prop['some-prop'] is undefined.

Known issue? Easy to work around, but works fine in plain js.

@einarq there isn't an intentional change there, but if you have a minimal repo or unit test for that that'd be great.

commented

@einarq / @markerikson - curious if changing:

delete state.assigned_[prop]

from:

delete state.assigned_[prop]

to:

delete state?.assigned_?.[prop]

and:

if (state.copy_) delete state.copy_[prop]

from:

delete state.copy_[prop]

to:

delete state?.copy_?.[prop]

will fix this?

i might attempt a fix/pr (and add a unit test)

EDIT: pr is here: #1031

@skratchdot, thanks for that! Sorry, missed the PR before from my spotty train connection, but can confirm the issue has been reproduced and fixed, and will be part of the final release

@skratchdot, thanks for that! Sorry, missed the PR before from my spotty train connection, but can confirm the issue has been reproduced and fixed, and will be part of the final release

Immer 10 released couple of week ago :)