Skip to content

Commit 3a01428

Browse files
authored
refactor(mutative): repalce immer with mutative (#97)
1 parent 0ae9af3 commit 3a01428

File tree

12 files changed

+74
-80
lines changed

12 files changed

+74
-80
lines changed

packages/reactant-model/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
],
2222
"license": "MIT",
2323
"peerDependencies": {
24-
"immer": "^9.0.15",
24+
"mutative": "^0.2.1",
2525
"reactant-module": "*"
2626
},
2727
"devDependencies": {
28-
"immer": "^9.0.15",
28+
"mutative": "^0.2.1",
2929
"reactant-module": "^0.70.0"
3030
}
3131
}

packages/reactant-model/src/model.ts

+17-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { produce, produceWithPatches, Patch, Immutable } from 'immer';
1+
import { create, Patch, Immutable } from 'mutative';
22
import {
33
storeKey,
44
Service,
55
stateKey,
66
actionIdentifier,
77
enablePatchesKey,
8+
enableAutoFreezeKey,
89
identifierKey,
910
nameKey,
1011
} from 'reactant-module';
@@ -34,16 +35,26 @@ export const model = <
3435
let patches: Patch[] | undefined;
3536
let inversePatches: Patch[] | undefined;
3637
if (module[enablePatchesKey]) {
37-
[state, patches, inversePatches] = produceWithPatches(
38-
module[stateKey],
38+
[state, patches, inversePatches] = create(
39+
module[stateKey] as S,
3940
(draftState: S) => {
4041
fn(...args)(draftState);
42+
},
43+
{
44+
enablePatches: true,
45+
enableAutoFreeze: module[enableAutoFreezeKey],
4146
}
4247
);
4348
} else {
44-
state = produce(module[stateKey], (draftState: S) => {
45-
fn(...args)(draftState);
46-
});
49+
state = create(
50+
module[stateKey] as S,
51+
(draftState: S) => {
52+
fn(...args)(draftState);
53+
},
54+
{
55+
enableAutoFreeze: module[enableAutoFreezeKey],
56+
}
57+
);
4758
}
4859
const lastState = module[storeKey]?.getState();
4960
module[storeKey]!.dispatch({

packages/reactant-model/test/index.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
PluginModule,
1010
stateKey,
1111
} from 'reactant-module';
12-
import { applyPatches } from 'immer';
12+
import { apply as applyPatches } from 'mutative';
1313
import { model } from '..';
1414

1515
test('base model with `useValue`', () => {

packages/reactant-module/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
],
2727
"license": "MIT",
2828
"dependencies": {
29-
"immer": "^9.0.15",
29+
"mutative": "^0.2.1",
3030
"reactant-di": "^0.70.0",
3131
"redux": "^4.1.0"
3232
},

packages/reactant-module/src/constants/reduxKeys.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ export const unsubscriptionsKey: unique symbol = Symbol('unsubscriptions');
55
export const stateKey: unique symbol = Symbol('state');
66
export const defaultStateKey: unique symbol = Symbol('defaultState');
77
export const enablePatchesKey: unique symbol = Symbol('enablePatches');
8+
export const enableAutoFreezeKey: unique symbol = Symbol('enableAutoFreeze');
89
export const enableInspectorKey: unique symbol = Symbol('enableInspector');
910
export const actionIdentifier = 'REACTANT_ACTION' as const;

packages/reactant-module/src/core/createStore.ts

+11-15
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,7 @@
33
/* eslint-disable guard-for-in */
44
/* eslint-disable @typescript-eslint/no-empty-function */
55
/* eslint-disable no-loop-func */
6-
import {
7-
enablePatches as enablePatchesWithImmer,
8-
produce,
9-
setAutoFreeze,
10-
} from 'immer';
6+
import { create } from 'mutative';
117
import {
128
Container,
139
getMetadata,
@@ -30,6 +26,7 @@ import {
3026
containerKey,
3127
defaultStateKey,
3228
enablePatchesKey,
29+
enableAutoFreezeKey,
3330
identifierKey,
3431
loaderKey,
3532
modulesKey,
@@ -90,17 +87,10 @@ export function createStore<T = any>({
9087
let store: ReactantStore | undefined = originalStore;
9188
let reducers: ReducersMapObject = {};
9289
const subscriptions: Subscriptions[] = [];
93-
// TODO: replace with `mutative`
94-
const enableAutoFreeze = devOptions.autoFreeze ?? true;
90+
const enableAutoFreeze = devOptions.autoFreeze ?? false;
9591
const enableReduxDevTools = devOptions.reduxDevTools ?? __DEV__;
9692
const enablePatches = devOptions.enablePatches ?? false;
9793
const enableInspector = devOptions.enableInspector ?? false;
98-
if (typeof store === 'undefined') {
99-
setAutoFreeze(enableAutoFreeze);
100-
if (enablePatches) {
101-
enablePatchesWithImmer();
102-
}
103-
}
10494

10595
dynamicModules.forEach((module, key) => {
10696
try {
@@ -198,7 +188,7 @@ export function createStore<T = any>({
198188
}
199189

200190
const initState = enableAutoFreeze
201-
? produce({ ...service[stateKey] }, () => {}) // freeze init state
191+
? create({ ...service[stateKey] }, () => {}, { enableAutoFreeze }) // freeze init state
202192
: service[stateKey]!;
203193
Object.assign(descriptors, {
204194
[initStateKey]: {
@@ -324,7 +314,13 @@ export function createStore<T = any>({
324314
load(...args);
325315
},
326316
},
327-
// enablePatches options for immer
317+
// enableAutoFreeze options for mutative
318+
[enableAutoFreezeKey]: {
319+
enumerable: false,
320+
configurable: false,
321+
value: enableAutoFreeze,
322+
},
323+
// enablePatches options for mutative
328324
[enablePatchesKey]: {
329325
enumerable: false,
330326
configurable: false,

packages/reactant-module/src/decorators/action.ts

+31-30
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
/* eslint-disable no-console */
22
/* eslint-disable func-names */
3-
import { produce, produceWithPatches, Patch } from 'immer';
3+
import { create, Patch } from 'mutative';
44
import { ReactantAction, Service } from '../interfaces';
55
import {
66
storeKey,
77
actionIdentifier,
88
enablePatchesKey,
9+
enableAutoFreezeKey,
910
identifierKey,
1011
enableInspectorKey,
1112
} from '../constants';
@@ -61,38 +62,45 @@ const action = (
6162
}' decorated by '@action' must be bound to the current class instance.`
6263
);
6364
}
64-
let time: number;
65-
if (__DEV__) {
66-
time = Date.now();
67-
}
6865
if (typeof stagedState === 'undefined') {
6966
try {
7067
const lastState = this[storeKey]?.getState();
7168
let state: Record<string, unknown>;
7269
let patches: Patch[] | undefined;
7370
let inversePatches: Patch[] | undefined;
7471
if (this[enablePatchesKey]) {
75-
[state, patches, inversePatches] = produceWithPatches<
76-
Record<string, unknown>
77-
>(lastState, (draftState) => {
78-
stagedState = draftState;
79-
const result = fn.apply(this, args);
80-
if (__DEV__ && result !== undefined) {
81-
throw new Error(
82-
`The return value of the method '${key}' is not allowed.`
83-
);
72+
[state, patches, inversePatches] = create(
73+
lastState,
74+
(draftState) => {
75+
stagedState = draftState;
76+
const result = fn.apply(this, args);
77+
if (__DEV__ && result !== undefined) {
78+
throw new Error(
79+
`The return value of the method '${key}' is not allowed.`
80+
);
81+
}
82+
},
83+
{
84+
enablePatches: true,
85+
enableAutoFreeze: this[enableAutoFreezeKey],
8486
}
85-
});
87+
);
8688
} else {
87-
state = produce<Record<string, unknown>>(lastState, (draftState) => {
88-
stagedState = draftState;
89-
const result = fn.apply(this, args);
90-
if (__DEV__ && result !== undefined) {
91-
throw new Error(
92-
`The return value of the method '${key}' is not allowed.`
93-
);
89+
state = create(
90+
lastState,
91+
(draftState) => {
92+
stagedState = draftState;
93+
const result = fn.apply(this, args);
94+
if (__DEV__ && result !== undefined) {
95+
throw new Error(
96+
`The return value of the method '${key}' is not allowed.`
97+
);
98+
}
99+
},
100+
{
101+
enableAutoFreeze: this[enableAutoFreezeKey],
94102
}
95-
});
103+
);
96104
}
97105
stagedState = undefined;
98106
if (__DEV__) {
@@ -104,13 +112,6 @@ const action = (
104112
`There are no state updates to method '${methodName}'`
105113
);
106114
}
107-
// performance checking
108-
const executionTime = Date.now() - time!;
109-
if (executionTime > 100)
110-
console.warn(
111-
`The execution time of method '${methodName}' is ${executionTime} ms, it's recommended to use 'dispatch()' API.`
112-
);
113-
// performance detail: https://immerjs.github.io/immer/docs/performance
114115
}
115116
this[storeKey]!.dispatch<ReactantAction>({
116117
type: this[identifierKey]!,

packages/reactant-module/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export { applyPatches } from 'immer';
1+
export { apply as applyPatches } from 'mutative';
22
export {
33
inject,
44
optional,

packages/reactant-module/src/interfaces.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type {
99
Unsubscribe,
1010
ReducersMapObject,
1111
} from 'redux';
12-
import type { Patch } from 'immer';
12+
import type { Patch } from 'mutative';
1313
import type { EnhancerOptions } from 'redux-devtools-extension';
1414
import type {
1515
Container,
@@ -24,6 +24,7 @@ import {
2424
actionIdentifier,
2525
loaderKey,
2626
enablePatchesKey,
27+
enableAutoFreezeKey,
2728
containerKey,
2829
identifierKey,
2930
nameKey,
@@ -76,6 +77,7 @@ export interface Service<T extends Record<string, any> = Record<string, any>> {
7677
readonly [storeKey]?: ReduxStore;
7778
readonly [loaderKey]?: Loader;
7879
readonly [enablePatchesKey]?: boolean;
80+
readonly [enableAutoFreezeKey]?: boolean;
7981
readonly [enableInspectorKey]?: boolean;
8082
readonly [subscriptionsKey]?: Subscriptions;
8183
readonly [unsubscriptionsKey]?: Set<Unsubscribe>;

packages/reactant-module/test/decorators/action.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { applyPatches } from 'immer';
1+
import { apply as applyPatches } from 'mutative';
22
import { Middleware } from 'redux';
33
import {
44
injectable,

packages/reactant-share/src/client.ts

-17
Original file line numberDiff line numberDiff line change
@@ -41,24 +41,7 @@ export const handleClient = ({
4141
const patches = enablePatchesFilter
4242
? action._patches!.filter((item) => currentState[item.path[0]])
4343
: action._patches!;
44-
let time: number;
45-
if (__DEV__) {
46-
// performance checking
47-
time = Date.now();
48-
}
4944
const state = applyPatches(currentState, patches);
50-
if (__DEV__) {
51-
const executionTime = Date.now() - time!;
52-
if (executionTime > 100)
53-
console.warn(
54-
`The 'applyPatches()' execution time from the method '${
55-
action.method
56-
}' in '${
57-
action.type as string
58-
}' is ${executionTime} ms, it's recommended to use 'dispatch()' API.`
59-
);
60-
// performance detail: https://immerjs.github.io/immer/docs/performance
61-
}
6245
app.store!.dispatch({ ...action, state });
6346
} else {
6447
app.store!.dispatch(action);

yarn.lock

+5-5
Original file line numberDiff line numberDiff line change
@@ -6716,11 +6716,6 @@ image-size@^0.6.0:
67166716
resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.6.3.tgz#e7e5c65bb534bd7cdcedd6cb5166272a85f75fb2"
67176717
integrity sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA==
67186718

6719-
immer@^9.0.15:
6720-
version "9.0.15"
6721-
resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.15.tgz#0b9169e5b1d22137aba7d43f8a81a495dd1b62dc"
6722-
integrity sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==
6723-
67246719
"immutable@^3.8.1 || ^4.0.0":
67256720
version "4.1.0"
67266721
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef"
@@ -9055,6 +9050,11 @@ multimatch@^5.0.0:
90559050
arrify "^2.0.1"
90569051
minimatch "^3.0.4"
90579052

9053+
mutative@^0.2.1:
9054+
version "0.2.1"
9055+
resolved "https://registry.yarnpkg.com/mutative/-/mutative-0.2.1.tgz#f22fbb7f02d563ec0be4410ec73e84a68af25c04"
9056+
integrity sha512-1W5D+k0wa8RMqnKrtXCmUOj16ywoJSs/9FQUw2PlPMGvFcAMIP4/N2kbIylEq5juCVNgfAwjocK4+H1/Fvttlg==
9057+
90589058
90599059
version "0.0.7"
90609060
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"

0 commit comments

Comments
 (0)