@modern-js/main-doc 2.7.0 → 2.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +17 -0
  3. package/README.md +2 -2
  4. package/en/apis/app/commands.mdx +2 -0
  5. package/en/apis/app/runtime/model/connect.mdx +1 -1
  6. package/en/apis/app/runtime/model/model_.mdx +1 -1
  7. package/en/apis/app/runtime/model/use-model.mdx +1 -1
  8. package/en/apis/app/runtime/web-server/hook.mdx +2 -2
  9. package/en/apis/app/runtime/web-server/middleware.mdx +33 -9
  10. package/en/components/enable-bff.mdx +4 -4
  11. package/en/components/init-rspack-app.mdx +7 -0
  12. package/en/configure/app/bff/enable-handle-web.mdx +24 -0
  13. package/en/configure/app/server/enable-framework-ext.mdx +1 -1
  14. package/en/guides/advanced-features/bff/_category_.json +1 -1
  15. package/en/guides/advanced-features/eslint.mdx +30 -32
  16. package/en/guides/advanced-features/low-level.mdx +1 -1
  17. package/en/guides/advanced-features/rspack-start.mdx +13 -17
  18. package/en/guides/advanced-features/web-server.mdx +87 -20
  19. package/en/guides/concept/builder.mdx +1 -1
  20. package/en/guides/topic-detail/framework-plugin/extend.mdx +20 -19
  21. package/en/guides/topic-detail/framework-plugin/hook-list.mdx +156 -155
  22. package/en/guides/topic-detail/framework-plugin/hook.mdx +58 -43
  23. package/en/guides/topic-detail/framework-plugin/implement.mdx +47 -49
  24. package/en/guides/topic-detail/framework-plugin/introduction.mdx +22 -23
  25. package/en/guides/topic-detail/framework-plugin/plugin-api.mdx +13 -13
  26. package/en/guides/topic-detail/framework-plugin/relationship.mdx +30 -30
  27. package/en/guides/topic-detail/generator/plugin/develop.mdx +1 -1
  28. package/en/guides/topic-detail/micro-frontend/c01-introduction.mdx +17 -17
  29. package/en/guides/topic-detail/micro-frontend/c02-development.mdx +76 -78
  30. package/en/guides/topic-detail/micro-frontend/c03-main-app.mdx +57 -51
  31. package/en/guides/topic-detail/micro-frontend/c04-communicate.mdx +11 -11
  32. package/en/guides/topic-detail/micro-frontend/c05-mixed-stack.mdx +13 -13
  33. package/en/guides/topic-detail/model/auto-actions.mdx +18 -21
  34. package/en/guides/topic-detail/model/computed-state.mdx +27 -25
  35. package/en/guides/topic-detail/model/define-model.mdx +14 -14
  36. package/en/guides/topic-detail/model/faq.mdx +12 -13
  37. package/en/guides/topic-detail/model/manage-effects.mdx +43 -52
  38. package/en/guides/topic-detail/model/model-communicate.mdx +47 -45
  39. package/en/guides/topic-detail/model/performance.mdx +22 -23
  40. package/en/guides/topic-detail/model/quick-start.mdx +29 -28
  41. package/en/guides/topic-detail/model/redux-integration.mdx +7 -7
  42. package/en/guides/topic-detail/model/test-model.mdx +11 -11
  43. package/en/guides/topic-detail/model/typescript-best-practice.mdx +16 -15
  44. package/en/guides/topic-detail/model/use-model.mdx +40 -45
  45. package/en/guides/topic-detail/model/use-out-of-modernjs.mdx +16 -16
  46. package/en/guides/troubleshooting/cli.mdx +2 -2
  47. package/package.json +5 -5
  48. package/zh/apis/app/commands.mdx +2 -0
  49. package/zh/apis/app/runtime/model/connect.mdx +1 -1
  50. package/zh/apis/app/runtime/model/model_.mdx +1 -1
  51. package/zh/apis/app/runtime/model/use-model.mdx +1 -1
  52. package/zh/apis/app/runtime/web-server/hook.mdx +2 -4
  53. package/zh/apis/app/runtime/web-server/middleware.mdx +30 -10
  54. package/zh/apis/monorepo/commands/gen-release-note.mdx +3 -3
  55. package/zh/components/enable-bff.mdx +4 -4
  56. package/zh/components/init-rspack-app.mdx +7 -0
  57. package/zh/components/release-note.mdx +1 -1
  58. package/zh/configure/app/bff/enable-handle-web.mdx +24 -0
  59. package/zh/configure/app/server/enable-framework-ext.mdx +1 -1
  60. package/zh/guides/advanced-features/bff/_category_.json +1 -1
  61. package/zh/guides/advanced-features/rspack-start.mdx +13 -17
  62. package/zh/guides/advanced-features/web-server.mdx +81 -16
  63. package/zh/guides/concept/builder.mdx +1 -1
  64. package/zh/guides/topic-detail/changesets/github.mdx +2 -2
  65. package/zh/guides/topic-detail/changesets/release-note.mdx +1 -1
  66. package/zh/guides/topic-detail/framework-plugin/plugin-api.mdx +2 -2
  67. package/zh/guides/topic-detail/generator/plugin/develop.mdx +1 -1
  68. package/zh/guides/topic-detail/model/faq.mdx +1 -1
  69. package/zh/guides/topic-detail/model/manage-effects.mdx +1 -1
  70. package/zh/guides/topic-detail/model/model-communicate.mdx +1 -1
  71. package/zh/guides/topic-detail/model/performance.mdx +1 -1
  72. package/zh/guides/topic-detail/model/quick-start.mdx +2 -2
  73. package/zh/guides/topic-detail/model/use-model.mdx +3 -3
@@ -1,24 +1,23 @@
1
1
  ---
2
2
  sidebar_position: 13
3
- title: 常见问题
3
+ title: FAQ
4
4
  ---
5
5
 
6
- # 常见问题
6
+ # FAQ
7
7
 
8
- ## 浏览器兼容性
8
+ ## Browser Compatibility
9
9
 
10
- Reduck 的编译构建产物默认使用 ES6 语法,如果你需要支持更低版本的浏览器,请将 `@modern-js-reduck` 命名空间下的所有包加入到应用的编译过程。
11
-
12
- :::info 补充信息
13
- Reduck 使用的 [`@babel/preset-env`](https://babeljs.io/docs/en/babel-preset-env) 的详细[配置](https://github.com/modern-js-dev/reduck/blob/main/common/config.js#L10~L17)。
10
+ The compiled build artifacts of Reduck use ES6 syntax by default. If you need to support older versions of browsers, please include all packages under the `@modern-js-reduck` namespace in your application's build process.
14
11
 
12
+ :::info Additional Information
13
+ Reduck uses [`@babel/preset-env`](https://babeljs.io/docs/en/babel-preset-env) with [specific configurations](https://github.com/web-infra-dev/reduck/blob/main/common/config.js#L10~L17).
15
14
  :::
16
15
 
17
- ## 微前端子应用 Model 访问主应用 Model
16
+ ## Accessing the Main Application Model from a Microfrontend Sub-Application Model
18
17
 
19
- 微前端子应用 Model 访问主应用 Model 时,如果该 **Model** 在主应用尚未挂载,会自动挂载到子应用上。
18
+ When a microfrontend sub-application model accesses the main application model and the model has not yet been mounted on the main application, it will be automatically mounted on the sub-application.
20
19
 
21
- 示例:
20
+ Example:
22
21
 
23
22
  ```ts
24
23
  import { useModel } from '@modern-js/runtime/model';
@@ -31,11 +30,11 @@ function SubModelApp() {
31
30
  }
32
31
  ```
33
32
 
34
- ![微前端通信流程图](https://lf3-static.bytednsdoc.com/obj/eden-cn/aphqeh7uhohpquloj/modern-js/docs/mf-communicate.svg)
33
+ ![Microfrontend Communication Flowchart](https://lf3-static.bytednsdoc.com/obj/eden-cn/aphqeh7uhohpquloj/modern-js/docs/mf-communicate.svg)
35
34
 
36
- 为了避免意外降级挂载,建议将主应用所需要共享的 Model 预先挂载:
35
+ To avoid accidental downgrades, it is recommended to pre-mount the model that the main application needs to share:
37
36
 
38
37
  ```ts
39
- // App 是主应用的入口组件,sharedModel1sharedModel2 是需要共享的 Model。
38
+ // App is the entry component of the main application, and sharedModel1 and sharedModel2 are the models that need to be shared.
40
39
  App.models = [sharedModel1, sharedModel2];
41
40
  ```
@@ -1,16 +1,16 @@
1
1
  ---
2
2
  sidebar_position: 5
3
- title: 副作用管理
3
+ title: Management Effect
4
4
  ---
5
- # 副作用管理
5
+ # Management Effect
6
6
 
7
- Model 中的 Action 必须是一个纯函数,执行过程中不会产生任何副作用。但在真实的业务中,我们会遇到很多副作用场景,如:请求 HTTP 接口获取状态数据,或者在更新状态的同时修改 localStorage、发送事件等。在 Reduck 中,是通过 Model Effects 函数管理副作用的。
7
+ The actions in the model must be pure functions and cannot have any side effects during execution. However, in real-world scenarios, we often encounter many side effects, such as: requesting data from an HTTP API to obtain state data, or modifying `localStorage` or sending events while updating the state. In Reduck, side effects are managed through the model's `effects` function.
8
8
 
9
- ## 副作用对 State 修改
9
+ ## Modifying State via Side Effects
10
10
 
11
- 副作用修改 State,最常见的场景就是请求 HTTP 接口,更新状态数据。
11
+ The most common scenario in which side effects modify the state is requesting data from an HTTP API to update state data.
12
12
 
13
- 我们以一个简单的 `todoModel` 为例。其有一个 `load` 的副作用函数,请求远端的 TODO 列表,请求成功之后更新 `state.items` 字段。
13
+ Let's take a simple `todoModel` as an example. It has a side effect function `load` that requests the TODO list from a remote server. After the request succeeds, it updates the `state.items` field.
14
14
 
15
15
  ```ts
16
16
  const todoModel = model('todo').define({
@@ -35,7 +35,7 @@ const todoModel = model('todo').define({
35
35
  },
36
36
  },
37
37
  effects: {
38
- // Promise 副作用
38
+ // Promise effects
39
39
  async load() {
40
40
  return new Promise(resolve => {
41
41
  setTimeout(() => resolve(['Learn Modern.js']), 2000);
@@ -45,22 +45,22 @@ const todoModel = model('todo').define({
45
45
  });
46
46
  ```
47
47
 
48
- 副作用函数统一定义在 `effects` 字段下。这里我们写了一个 `load` 函数,它返回一个 PromisePromise 执行成功后,返回 TODO 列表 `["Lerna Modern.js"]`。
48
+ The side effect function is uniformly defined under the `effects` field. Here we have written a `load` function that returns a Promise. After the Promise is successfully executed, it returns the TODO list `["Lerna Modern.js"]`.
49
49
 
50
- 副作用函数需要和 actions 配合使用,才能完成状态的修改。因此,我们在 `actions` 中定义了一个 `load`(命名需要和 `effects` 下的副作用函数的名字保持一致)对象,包含 `pending`、`fulfilled`、`rejected` 3 action,分别是对副作用函数 `load` 返回的 `Promise` 的三种状态( pending、fulfilled、rejected )的处理:
50
+ Side effect functions need to work with actions to modify state. Therefore, we define a `load` object in `actions` (the name needs to be consistent with the name of the side effect function under `effects`), which includes three actions (`pending`, `fulfilled`, `rejected`) that handle the three states (`pending`, `fulfilled`, `rejected`) of the `Promise` returned by the side effect function `load`:
51
51
 
52
- - `pending`:接收当前状态 `state` 作为参数,新的状态中 `loading` 设为 `true`。
53
- - `fulfilled`:接收当前状态 `state` Promise fulfilled 状态的值 `items` 为参数,新的状态中 `items` 等于参数 `items`、`loading` 设为 `false`。
54
- - `rejected`:接收当前状态 `state` Promise rejected 状态的错误 `error` 为参数,新的状态中 `error` 等于参数 `error`、`loading` 设为 `false`。
52
+ - `pending`: Receives the current state `state` as a parameter and sets the `loading` flag to `true` in the new state.
53
+ - `fulfilled`: Receives the current state `state` and the Promise fulfilled value `items` as parameters, and sets `items` to the parameter `items` and `loading` to `false` in the new state.
54
+ - `rejected`: Receives the current state `state` and the Promise rejected error `error` as parameters, and sets `error` to the parameter `error` and `loading` to `false` in the new state.
55
55
 
56
- 组件中如何调用 effects 函数呢? effects 函数会被合并到 actions 对象上,因此可以通过 actions 对象调用 effects 函数,如下所示:
56
+ How do we call the effects function in the component? The effects function will be merged into the actions object, so you can call the effects function through the actions object, as shown below:
57
57
 
58
58
  ```ts
59
59
  function Todo() {
60
60
  const [state, actions] = useModel(todoModel);
61
61
 
62
62
  useEffect(() => {
63
- // 调用 effects 函数
63
+ // invoke effects function
64
64
  actions.load();
65
65
  }, []);
66
66
 
@@ -80,9 +80,9 @@ function Todo() {
80
80
  }
81
81
  ```
82
82
 
83
- 上面的示例中, `pending`、`fulfilled`、`rejected` 3 action,对于用于获取数据的 HTTP 请求场景下,一般都是需要的。Reduck 提供了一个工具函数 `handleEffect`,用于简化这种场景下的 action 创建。
83
+ In the example above, the three actions `pending`, `fulfilled`, and `rejected` are generally required for HTTP requests used to obtain data. Reduck provides a utility function `handleEffect` to simplify the creation of actions in this scenario.
84
84
 
85
- `handleEffect` 约定这种副作用场景下, Model State 结构包含 `result`、`error`、`pending` 3 个字段,初始值为:
85
+ For this type of side effect scenario, `handleEffect` stipulates that the state structure of the model contains three fields: `result`, `error`, and `pending`, with initial values of:
86
86
 
87
87
  ```ts
88
88
  {
@@ -92,7 +92,7 @@ function Todo() {
92
92
  }
93
93
  ```
94
94
 
95
- 调用 `handleEffect` 会返回如下数据结构:
95
+ Calling `handleEffect` will return the following data structure:
96
96
 
97
97
  ```ts
98
98
  {
@@ -102,9 +102,9 @@ function Todo() {
102
102
  }
103
103
  ```
104
104
 
105
- 这个数据结构和我们在 `actions` 下的 `load` 对象的数据结构是相同的。`handleEffect` 返回的对象,其实就是对应了 Effects 函数需要的 3 action。
105
+ This data structure is the same as the data structure of the `load` object under `actions`. The object returned by `handleEffect` actually corresponds to the three actions required by the Effects function.
106
106
 
107
- 利用 `handleEffect`,改写 `todoModel`:
107
+ We can use `handleEffect` to rewrite `todoModel`:
108
108
 
109
109
  ```ts
110
110
  const todoModel = model('todo').define({
@@ -117,7 +117,7 @@ const todoModel = model('todo').define({
117
117
  load: handleEffect({ result: 'items' }),
118
118
  },
119
119
  effects: {
120
- // Promise 副作用
120
+ // Promise effects
121
121
  async load() {
122
122
  return new Promise(resolve => {
123
123
  setTimeout(() => resolve(['Learn Modern.js']), 2000);
@@ -127,29 +127,26 @@ const todoModel = model('todo').define({
127
127
  });
128
128
  ```
129
129
 
130
- `handleEffect` 接收的参数对象,将 `result` 设置为 `item`。因为 `todoModel` state,使用 `items` 作为 key 保存 todo 列表数据,而不是使用 `handleEffect` 默认的 `result` 作为 key,所以这里需要进行配置。
130
+ The `handleEffect` function sets `result` to `items` in the received parameter object. Because `todoModel` uses `items` as the key to save the TODO list data instead of using the default `result` as the key of `handleEffect`, configuration is required here.
131
131
 
132
- 明显可见,通过 `handleEffect` 实现的 `todoModel` 比之前的实现有了很大精简。
132
+ It is obvious that the `todoModel` implemented through `handleEffect` is much more concise than the previous implementation.
133
133
 
134
- 如果不希望 pendingfulfilledrejected 3 种状态都被 `handleEffect` 自动处理,例如 fulfilled 需要手动处理较复杂的数据类型,但是 pendingrejected 依旧想进行自动化处理,可以参考如下写法:
134
+ If you do not want all three states (pending, fulfilled, rejected) to be automatically handled by `handleEffect`, for example, if the fulfilled state requires more complex data processing and needs to be manually handled, but you still want to automate the handling of the pending and rejected states, you can use the following method:
135
135
 
136
136
  ```ts
137
137
  actions: {
138
138
  load: {
139
139
  ...handleEffect(),
140
140
  fulfilled(state, payload) {
141
- // 手动处理
141
+ // manual handle
142
142
  },
143
143
  },
144
144
  },
145
145
  ```
146
146
 
147
- :::info 补充信息
148
- `handleEffect` [API](/apis/app/runtime/model/handle-effect)。
147
+ `handleEffect` [API](/apis/app/runtime/model/handle-effect).
149
148
 
150
- :::
151
-
152
- Effects 函数中,也支持手动调用 Actions,例如:
149
+ In the Effects function, you can also manually call Actions. For example:
153
150
 
154
151
  ```ts
155
152
  const todoModel = model('todo').define((context, utils) => ({
@@ -169,15 +166,15 @@ const todoModel = model('todo').define((context, utils) => ({
169
166
  },
170
167
  effects: {
171
168
  async load() {
172
- // 通过 utils.use 获取当前 Model 对象的 actions
169
+ // use utils.use get cuttent Model actions
173
170
  const [, actions] = utils.use(todoModel);
174
- // 手动调用 action
171
+ // invoke action
175
172
  actions.pending();
176
173
 
177
174
  return new Promise(resolve => {
178
175
  setTimeout(() => {
179
176
  const items = ['Learn Modern.js'];
180
- // 手动调用 action
177
+ // invoke action
181
178
  actions.fulfilled(items);
182
179
  resolve(items);
183
180
  }, 2000);
@@ -187,16 +184,13 @@ const todoModel = model('todo').define((context, utils) => ({
187
184
  }));
188
185
  ```
189
186
 
190
- :::info
191
- 可以使用 `use` 函数加载其它 Model(包括 Model 自身),实现 [Model 间通信](/guides/topic-detail/model/model-communicate)。
192
-
193
- :::
187
+ You can use the `use` function to load other Models (including the Model itself) to achieve [Model communication](/guides/topic-detail/model/model-communicate).
194
188
 
195
- ## 副作用不影响 state
189
+ ## Side effects do not affect state
196
190
 
197
- 有些场景下,我们只需要读取 State,执行相关副作用逻辑,副作用不会修改 State
191
+ In some cases, we only need to read State and execute relevant side effect logic, and the side effect will not modify State.
198
192
 
199
- 例如,存储某些 State `localStorage`:
193
+ For example, store some State in `localStorage`:
200
194
 
201
195
  ```ts
202
196
  const fooModel = model('foo').define((context, utils) => ({
@@ -213,7 +207,7 @@ const fooModel = model('foo').define((context, utils) => ({
213
207
  }));
214
208
  ```
215
209
 
216
- 或者是向服务端发送数据:
210
+ or send message to server:
217
211
 
218
212
  ```ts
219
213
  const fooModel = model('foo').define({
@@ -232,29 +226,26 @@ const fooModel = model('foo').define({
232
226
  });
233
227
  ```
234
228
 
235
- ## 副作用函数返回值
236
-
237
- 有时候,我们希望能根据副作用函数的执行结果,直接执行后续逻辑。这时候,就需要使用 Effects 函数的返回。
229
+ Sometimes, we want to execute subsequent logic directly based on the execution result of the side effect function. In this case, we need to use the return value of the Effects function.
238
230
 
239
- 例如,当点击发送按钮,发送数据成功后,立即关闭当前的弹窗;如果失败,显示错误信息。我们可以通过如下代码实现:
231
+ For example, when the send button is clicked and the data is successfully sent, close the current popup immediately; if it fails, display an error message. We can achieve this through the following code:
240
232
 
241
233
  ```ts
242
- // 代码仅做示意,不能执行
243
- // 组件内部 发送按钮 的响应函数
234
+ // The code is for illustration only and cannot be executed.
235
+ // Response function of the "send" button within the component.
244
236
  const handleClick = async () => {
245
- // sendData 返回代表状态的字符串
237
+ // sendData returns a string that represents the state.
246
238
  const result = await actions.sendData('some data');
247
239
  if (result === 'success') {
248
- // 关闭弹窗
240
+ // Close the popup window.
249
241
  closeModal();
250
242
  } else {
251
- // 显示错误
243
+ // show error
252
244
  showError(result);
253
245
  }
254
246
  };
255
247
  ```
256
248
 
257
- :::info 补充信息
258
- [示例代码](https://github.com/modern-js-dev/modern-js-examples/tree/main/series/tutorials/runtime-api/model/effects)
259
-
249
+ :::info
250
+ [Example](https://github.com/web-infra-dev/modern-js-examples/tree/main/series/tutorials/runtime-api/model/effects)
260
251
  :::
@@ -1,21 +1,22 @@
1
1
  ---
2
2
  sidebar_position: 7
3
- title: Model 通信
3
+ title: Model Communication
4
4
  ---
5
- # Model 通信
6
5
 
7
- Model 通信,既指不同 Model 间的通信,也指同一个 Model 内部 Effects、Actions 之间的通信。
6
+ # Model Communication
8
7
 
9
- ## Model 间通信
8
+ Model communication refers to communication between different Models, as well as communication between Effects and Actions within the same Model.
10
9
 
11
- Model 之间不是孤立的,是可以进行通信的。主要分为两种场景:
10
+ ## Communication between Models
12
11
 
13
- 1. Model 中访问其它 Model State Actions。
14
- 2. 在 Model 中监听其它 Model 变化。
12
+ Models are not isolated from each other and can communicate with each other. There are mainly two scenarios:
15
13
 
16
- 这里将 [快速上手](/guides/topic-detail/model/quick-start) 一节的简单计数器应用改造成一个可设置步频的计数器应用。可以通过设置步频,从而影响每次计数器增加的幅度。
14
+ 1. Accessing the State and Actions of other Models in the Model.
15
+ 2. Listening to changes in other Models in the Model.
17
16
 
18
- 我们抽象出两个 Model,分别为 `stepModel`(步频)、`counterModel`(计数器):
17
+ Here, we will transform the simple counter application in the [Quick Start](/guides/topic-detail/model/quick-start) section into a counter application that allows you to set the step frequency. By setting the step frequency, you can affect the magnitude of each counter increase.
18
+
19
+ We abstract two Models, `stepModel` (step frequency) and `counterModel` (counter):
19
20
 
20
21
  ```ts
21
22
  import { model } from '@modern-js/runtime/model';
@@ -51,18 +52,17 @@ const counterModel = model('count').define((context, { use, onMount }) => {
51
52
  export { stepModel, counterModel };
52
53
  ```
53
54
 
54
- `stepModel` 只声明一个 `state`,初始值为 1
55
-
56
- `counterModel` 通过 `use` 函数加载 `stepModel`,拿到返回的 `subscribeStep` 函数,用来监听 `stepModel` 状态的变更。 `onMount` 是 Model 挂载完成后的钩子函数,`counterModel` 挂载完成后开始订阅 `stepModel` 状态的变更,打印出 `stepModel` 的最新值。
55
+ `stepModel` declares only one `state`, with an initial value of 1.
57
56
 
58
- `counterModel` 通过 `use` 函数访问 `stepModel`,在 `add` 里可以获取到当前 `stepModel` 的值(步频),以此值来做自增。
57
+ `counterModel` loads `stepModel` with the `use` function, and retrieves the returned `subscribeStep` function to listen for changes to the `stepModel` state. `onMount` is a hook function that is executed after the Model is mounted. `counterModel` begins to subscribe to the state changes of `stepModel` after it has been mounted, and prints out the latest value of `stepModel`.
59
58
 
60
- :::caution 注意
61
- 当需要访问其他 Model 的 State 时,必须要在当前 Actions 或 Effects 函数(本例中对应 `add` 函数 )真正执行的阶段调用 `use`,以保证获取的 State 是最新值。因此,我们虽然在 `define` 的回调函数中也调用了 `use(stepModel)`,但是我们并没有解构 `stepModel` 的 `state` 值,因为 `define` 的回调函数是在 Model 的挂载阶段执行的,这个时候获取到的 `stepModel` 的 `state` 可能和 `add` 执行时获取到的值是不同的。
59
+ `counterModel` accesses `stepModel` using the `use` function, and in the `add` function, the current value of `stepModel` (step frequency) can be obtained to perform increments using this value.
62
60
 
61
+ :::caution Note
62
+ When you need to access the state of another Model, you must call `use` during the actual execution phase of the current Actions or Effects function (in this example, the `add` function) to ensure that the obtained State is the latest value. Therefore, although we also call `use(stepModel)` in the callback function of `define`, we do not destructure the `state` value of `stepModel` because the callback function of `define` is executed during the mounting phase of the Model, and at this time, the `state` of `stepModel` obtained may be different from the value obtained when `add` is executed.
63
63
  :::
64
64
 
65
- 修改 **App.tsx**
65
+ Modify App.tsx:
66
66
 
67
67
  ```tsx
68
68
  import { useModel } from '@modern-js/runtime/model';
@@ -87,45 +87,45 @@ export default function App() {
87
87
  }
88
88
  ```
89
89
 
90
- :::info 补充信息
91
- Modern.js 默认开启 [自动生成 actions](./auto-actions.mdx),所以 `stepModel` 中虽然没有手动定义 Actions,但可以使用自动生成的 `setState`。
90
+ :::info Additional Information
91
+ Modern.js has enabled [auto-generate actions](./auto-actions.mdx) by default, so even though there are no Actions defined manually in the `stepModel`, the auto-generated `setState` can still be used.
92
92
 
93
93
  :::
94
94
 
95
- - 点击 **add step** 增加步频。
96
- - 点击 **add counter** 触发计数器增加。
95
+ - Click **add step** to add steps.
96
+ - Click **add counter** to trigger the counter to increase.
97
97
 
98
- 最终效果如下:
98
+ The final effect is as follows:
99
99
 
100
100
  ![communicate-models](https://lf3-static.bytednsdoc.com/obj/eden-cn/aphqeh7uhohpquloj/modern-js/docs/models-communicate.gif)
101
101
 
102
- :::info 补充信息
103
- - 本节完整的[示例代码](https://github.com/modern-js-dev/modern-js-examples/tree/main/series/tutorials/runtime-api/model/models-communication)
104
- - 相关 API 的更多介绍,请参考:[model](/apis/app/runtime/model/model_#函数类型)
102
+ :::info Additional Information
103
+ - Full example code for this section can be found [here](https://github.com/web-infra-dev/modern-js-examples/tree/main/series/tutorials/runtime-api/model/models-communication).
104
+ - For more information about the relevant API, please refer to: [model](/apis/app/runtime/model/model_#function-types).
105
105
 
106
106
  :::
107
107
 
108
- 前面 `counterModel` 的例子,我们是在 Actions 的函数内部调用 `use` 获取其他 Model 对象的。如果只需要调用其它 Model Actions,因为 Actions 都是函数,不存在值过期问题,所以也可以在 `define` 的回调函数中调用 `use` 获取 Model Actions。例如:
108
+ In the previous example of `counterModel`, we called `use` within the Actions function to get other Model objects. If we only need to call Actions of other Models, we can also use `use` to get the Actions of Models in the `define` callback function because Actions are functions and there is no issue of value expiration. For example:
109
109
 
110
110
  ```ts
111
111
  const barModel = model('bar').define({
112
- // 省略
112
+ // ..
113
113
  });
114
114
 
115
115
  const fooModel = model('foo').define((context, utils) => {
116
- // 获取 barModel actions
116
+ // get barModel actions
117
117
  const [, actions] = utils.use(barModel);
118
118
  return {
119
- // 省略 state、actions
119
+ // ...
120
120
  effects: {
121
121
  async loadA() {
122
- // 省略副作用逻辑
123
- // 调用 barModel action
122
+ // ...
123
+ // invoke barModel action
124
124
  barModel.actionA();
125
125
  },
126
126
  async loadB() {
127
- // 省略副作用逻辑
128
- // 调用 barModel action
127
+ // ...
128
+ // invoke barModel action
129
129
  barModel.actionB();
130
130
  },
131
131
  },
@@ -133,18 +133,18 @@ const fooModel = model('foo').define((context, utils) => {
133
133
  });
134
134
  ```
135
135
 
136
- 这样,我们不需要在 `loadA`、`loadB` 中重复获取 `barModel` 对象,简化了代码逻辑。
136
+ Here, we no longer need to repeatedly get the `barModel` object in `loadA` and `loadB`, which simplifies the code logic.
137
137
 
138
- ## Model 内通信
138
+ ## Communication within a Model
139
139
 
140
- Model 内通信,也主要分为两种场景:
140
+ Communication within a Model can also be divided into two main scenarios:
141
141
 
142
- 1. Effects 函数调用自身 Model Actions 函数、或其他 Effects 函数。
143
- 2. Actions 函数调用自身 Model 其他 Actions 函数。
142
+ 1. Effects functions call the Actions functions of the same Model or other Effects functions.
143
+ 2. Actions functions call other Actions functions of the same Model.
144
144
 
145
- [副作用管理](/guides/topic-detail/model/manage-effects) 一节,我们演示过 Effects 函数如何调用 Actions 函数。
145
+ In the [Managing Side Effects](/guides/topic-detail/model/manage-effects) section, we demonstrated how Effects functions call Actions functions.
146
146
 
147
- 这里我们再来举一个例子:
147
+ Here we provide another example:
148
148
 
149
149
  ```ts
150
150
  const fooModel = model('foo').define((context, { use, onMount }) => ({
@@ -162,13 +162,13 @@ const fooModel = model('foo').define((context, { use, onMount }) => ({
162
162
  },
163
163
  effects: {
164
164
  async loadA() {
165
- // 通过 use 获取当前 Model actions
165
+ // get current Model actions
166
166
  const [, actions] = use(fooModel);
167
167
  const res = await mockFetchA();
168
168
  actions.setA(res);
169
169
  },
170
170
  async loadB() {
171
- // 通过 use 获取当前 Model actions
171
+ // get current Model actions
172
172
  const [, actions] = use(fooModel);
173
173
  const res = await mockFetchB();
174
174
  actions.setB(res);
@@ -177,16 +177,18 @@ const fooModel = model('foo').define((context, { use, onMount }) => ({
177
177
  }));
178
178
  ```
179
179
 
180
- 这个例子中,`fooModel` 的两个 Effects 函数,需要调用自身的 Actions 函数。这里我们在每个 Effects 函数中,都调用了一次 `use`,为什么不能像 Model 间通信的例子中,在 `define` 的回调函数中,统一调用 `use` 获取 Model 自身的 Actions 呢?这是因为调用 `use` 获取 Model 时,会先检查这个 Model 是否已经挂载,如果还没有挂载,会先执行挂载逻辑,而 `define` 的回调函数又是在 Model 的挂载阶段执行的,这样一来,在挂载阶段调用 `use` 获取 Model 自身,会出现死循环(代码实际执行过程会抛出错误)。所以,**一定不能在 `define` 的回调函数中,调用 `use` 获取 Model 自身对象。**
180
+ In this example, the two Effects functions of `fooModel` need to call their own Actions functions. Here, we have called `use` once in each Effects function. Why can't we use `use` to get the Actions of the Model itself in the `define` callback function, as in the example of Model communication? This is because when calling `use` to get a Model, it first checks whether the Model has been mounted. If it has not been mounted, the mounting logic will be executed first.
181
+
182
+ The `define` callback function is executed during the mounting phase, so calling `use` to get the Model itself during the mounting phase will result in an infinite loop (which will throw an error in the actual execution process). Therefore, **you must not call `use` in the `define` callback function to get the Model itself**.
181
183
 
182
- 不过,我们可以利用 `onMount` 这个钩子函数,在 Model 挂载完成后,再通过 `use` 获取 Model 自身对象:
184
+ However, we can use the `onMount` hook function to get the Model itself through `use` after the Model has been mounted:
183
185
 
184
186
  ```ts
185
187
  const fooModel = model('foo').define((context, { use, onMount }) => {
186
188
  let actions;
187
189
 
188
190
  onMount(() => {
189
- // fooModel 挂载完成后,通过 use 获取当前 Model 的 actions
191
+ // after fooModel mounted,get actions
190
192
  [, actions] = use(fooModel);
191
193
  });
192
194
 
@@ -217,4 +219,4 @@ const fooModel = model('foo').define((context, { use, onMount }) => {
217
219
  });
218
220
  ```
219
221
 
220
- 这样,我们也可以实现代码的简化。
222
+ In this way, we can also simplify the code.
@@ -1,16 +1,16 @@
1
1
  ---
2
2
  sidebar_position: 8
3
- title: 性能优化
3
+ title: Performance Optimization
4
4
  ---
5
- # 性能优化
5
+ # Performance Optimization
6
6
 
7
- Reduck 内部已经做了大量性能优化工作,一般情况下不需要考虑性能问题。不过当对性能比较敏感、或者遇到了性能问题,可以考虑从以下 3 个方面,进行更有针对性的性能优化。
7
+ Reduck has already done a lot of performance optimization work internally, so performance issues generally do not need to be considered. However, when performance is more sensitive, or when encountering performance issues, you can consider more targeted performance optimization from the following three aspects.
8
8
 
9
- ## Model 拆分
9
+ ## Splitting Models
10
10
 
11
- `useModel` 返回 Model 对象的完整 State 时,State 任意部分的变化都会导致调用了 `useModel` 的组件重新渲染。
11
+ When `useModel` returns the complete State object of the Model, any change in any part of the State will cause the component that calls `useModel` to be re-rendered.
12
12
 
13
- 例如:
13
+ For example:
14
14
 
15
15
  ```ts
16
16
  const fooModel = model('foo').define({
@@ -35,7 +35,7 @@ function ComponentA() {
35
35
  }
36
36
  ```
37
37
 
38
- 组件 `ComponentA` 虽然只需要使用 `a` 状态,但当 `b` 状态发送变化时, `ComponentA` 仍然会重新渲染。这种情况,我们可以考虑把 `fooModel` 拆分,`a`、`b` 分别由不同的 Model 负责管理:
38
+ Although `ComponentA` only needs to use the `a` state, it will still be re-rendered when the `b` state changes. In this case, we can consider splitting `fooModel` into separate Models responsible for managing `a` and `b` respectively:
39
39
 
40
40
  ```ts
41
41
  const fooModel = model('foo').define({
@@ -61,11 +61,11 @@ const barModel = model('bar').define({
61
61
  });
62
62
  ```
63
63
 
64
- ## 状态筛选
64
+ ## State Selection
65
65
 
66
- `useModel` 支持传入 selector 函数,对返回给组件的 State Actions 做筛选。我们可以通过 selector 函数,确保返回给组件的 State 是组件直接需要使用的,从而保证组件不会因为其他无关状态的变化而重新渲染。
66
+ `useModel` supports passing in a selector function to filter the returned State and Actions for the component. We can use a selector function to ensure that the State returned to the component is what the component needs directly, thus ensuring that the component is not re-rendered due to changes in other unrelated states.
67
67
 
68
- 对于上面同样的例子,我们采用 selector 函数进行性能优化,代码如下:
68
+ For the same example above, we can use a selector function for performance optimization, the code is as follows:
69
69
 
70
70
  ```ts
71
71
  const fooModel = model('foo').define({
@@ -91,11 +91,11 @@ function ComponentA() {
91
91
  }
92
92
  ```
93
93
 
94
- ## 衍生状态缓存
94
+ ## Derivative State Caching
95
95
 
96
- Model 存在 `computed` 时,每次调用`useModel` 都会执行 `computed` 函数。
96
+ When a Model has `computed` property, the `computed` function will be executed every time `useModel` is called.
97
97
 
98
- 考虑如下代码:
98
+ Consider the following code:
99
99
 
100
100
  ```ts
101
101
  const barModel = model('bar').define({
@@ -104,7 +104,7 @@ const barModel = model('bar').define({
104
104
  },
105
105
  computed: {
106
106
  combineA: [
107
- fooModel, // fooModel 定义同上
107
+ fooModel, // fooModel define as above
108
108
  (state, fooState) => {
109
109
  return state + fooState.a;
110
110
  },
@@ -120,18 +120,17 @@ const barModel = model('bar').define({
120
120
  function ComponentB() {
121
121
  const [state, actions] = useModel(fooModel);
122
122
  const [{ combineA }] = useModel(barModel);
123
- // 省略
123
+ // ...
124
124
  }
125
125
  ```
126
+ Even if the `b` state of `fooModel` changes, the `combineA` function (more precisely, the last function type element of `combineA`) will still be called and executed when the component is re-rendered, although the derivative state `combineA` of `barModel` depends on `barModel` itself and the state `a` of `fooModel`.
126
127
 
127
- `barModel` 的衍生状态 `combineA` 依赖 `barModel` 自身状态 `fooModel` 的状态 `a`,但是即使是 `fooModel` 的状态 `b` 发生了变化,组件重新渲染时, `combineA` (更准确的说法是 `combineA` 的最后一个函数类型的元素 )依然会被调用执行。
128
-
129
- 一般情况下,`computed` 函数中的逻辑都是非常轻量的,但当 `computed` 函数逻辑比较复杂时,我们可以考虑对计算逻辑做缓存。例如,我们使用 [reselect](https://github.com/reduxjs/reselect) 对 `barModel` 的 `combineA` 做缓存:
128
+ In general, the logic in the `computed` function is usually very lightweight, but when the logic in the `computed` function is relatively complex, we can consider caching the calculation logic. For example, we can use [reselect](https://github.com/reduxjs/reselect) to cache `combineA` of `barModel`:
130
129
 
131
130
  ```ts
132
131
  import 'createSelector' from 'reselect';
133
132
 
134
- // 创建缓存函数
133
+ // create cache function
135
134
  const selectCombineA = createSelector(
136
135
  (state) => state.bar.value,
137
136
  (state) => state.foo.a,
@@ -163,9 +162,9 @@ const barModel = model("bar").define({
163
162
  });
164
163
  ```
165
164
 
166
- 我们创建缓存函数 `createSelector`,仅当 `barModel` 的状态发生改变或 `fooModel` `a` 状态发生改变时,才会重新计算 `combineA` 的值。
167
-
168
- :::info 补充信息
169
- 本节完整的[示例代码](https://github.com/modern-js-dev/modern-js-examples/tree/main/series/tutorials/runtime-api/model/performance-optimization)
165
+ We created a caching function `createSelector`, which only recalculates the value of `combineA` when the state of `barModel` changes or the state `a` of `fooModel` changes.
170
166
 
167
+ :::info Additional Information
168
+ You can find the complete example code of this section [here](https://github.com/web-infra-dev/modern-js-examples/tree/main/series/tutorials/runtime-api/model/performance-optimization).
171
169
  :::
170
+