You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/MIDDLEWARE.md
+29-18Lines changed: 29 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -193,39 +193,50 @@ Polymiddleware enforces immutability of requests. Unlike legacy middleware, an u
193
193
194
194
### Why we think polymiddleware is better?
195
195
196
-
We start using middleware (or chain of responsibility) pattern for UI customization since late 2018 when React hooks is still in its womb. Over the past 7.5 years, we learnt a lot.
196
+
Since late 2018, we start adopting middleware programming pattern for UI customization. At the time, React hooks is still in its womb. Over the past 7.5 years of journey, we learnt a lot. Polymiddleware combined all our learnings and is our mature approach for deep customization.
197
197
198
198
- In other languages, middleware is called "chain of responsibility"
199
199
- Unique characteristics in Web Chat: bidirectional, synchronous, early termination
200
-
- Middleware overriding request offers flexibility but makes it very hard to debug
201
-
- Rendering become inconsistent when a buggy middleware is in the chain
202
-
- One middleware could change activity type and cause havoc
200
+
- The economy of middleware/chain-of-responsibility in plain English
201
+
- "In Web Chat, result is a render function"
202
+
- "Handler process a request and return a result"
203
+
- "Enhancer is a handler working in a chain: it process the request, pass it to the next enhancer to process, when it return, process it again, and then return"
204
+
- "Middleware initialize the chain of enhancers"
205
+
- "`applyMiddleware()` compile middleware back to a single handler"
206
+
- Allowing middleware to override request improves flexibility but also impact debuggability
207
+
- When a middleware in the chain is bugged, rendering could become inconsistent
208
+
- One middleware could change activity type and cause havoc
203
209
- Middleware should return render function than a React component
204
-
- Impossible to set a default prop (binding props) in React component without wasted rendering and various performance issues
205
-
- Hooks cannot be used in render function
210
+
- Impossible to set a dynamic value as a default prop value in React component without wasted rendering and various performance issues
211
+
- Binding props to a component always re-render despite no actual value change
212
+
- Render function cannot use hooks
206
213
- Render function and React component can be transformed to each other
207
-
- Ability to use hooks in middleware will reduce props and moving parts
208
-
- Build-time vs. render-time
209
-
- Request is build-time variable and primarily used to "decide whether middleware should add/remove/replace/decorate UI"
214
+
- Ideal scenario: web devs pass a React component, Web Chat render using render function
215
+
- Ability to use hooks in middleware will reduce prop-passing and result in cleaner interface
216
+
- Clear distinction between build-time and render-time
217
+
- Request is a build-time variable and primarily used to "decide whether middleware should add/remove/replace/decorate UI"
210
218
- Props and hooks are render-time variable and is for "how to render the UI"
211
219
- All UI-rendering middleware should share same API signature
212
220
- Card action and group activity middleware could be exempted because they are not UI-rendering
213
221
- Versioning API change is difficult
214
-
- Factory function can help backward and forward compatibility
215
-
- Props should be hide using React context as a wrapper
216
-
- Rendering flavor/variant should be part of the request but not a separate middleware
222
+
- Factory function can help backward and forward compatibility, similar to building a SDK for an API
223
+
- Props should be hidden by using wrapping React context
224
+
- Flavor of rendering should be part of the request but not a separate middleware
217
225
- "Attachment middleware for screen reader" could be avoided by adding a "for screen reader" flag in the request
218
-
- Everything should be a middleware, whether they are concrete (such as button and icon) or composed (such as send box)
219
-
- Error boundary should be the topmost middleware in the chain
226
+
- Everything should be a middleware, whether they are concrete (such as button and icon) or composed (such as send box, which is composed by text box and send button)
227
+
- Error boundary should be the topmost decorative middleware in the chain
228
+
- When re-rendering is needed due to middleware change, its corresponding callback hook should be invalidated
229
+
- When no middleware change, the callback hook should never be invalidated
230
+
- To render a middleware with a request, it can be either done by calling a callback hook, or rendering a proxy component
220
231
221
232
### Polyfilling legacy middleware
222
233
223
-
Legacy middleware passed to deprecating props such as `activityMiddleware` will be polyfilled to polymiddleware after other polymiddleware passed via the `polymiddleware` prop.
234
+
Legacy middleware passed to deprecating props such as `activityMiddleware` will be polyfilled to polymiddleware and placed after other polymiddleware passed via the `polymiddleware` prop. In other words, legacy middleware has lower priority than polymiddleware.
224
235
225
-
Special polymiddleware factory functions allow input of legacy middleware and output as polymiddleware. This helps the transition period. However, these special factory functions is also marked as deprecated.
236
+
Special polymiddleware factory functions such as `createActivityPolymiddlewareFromLegacy()`allow input of legacy middleware and output as polymiddleware. This helps the transition period. However, these special factory functions is also marked as deprecated.
226
237
227
-
### Why `createActivityPolymiddlewareFromLegacy` accepts an arary of legacy middleware instead of one?
238
+
### Why `createActivityPolymiddlewareFromLegacy()` accepts an array of legacy middleware instead of one?
228
239
229
240
Polymiddleware enforces immutability of requests, which differs from the behavior of legacy middleware.
230
241
231
-
When multiple legacy middleware are passed as an array into`createActivityPolymiddlewareFromLegacy()`, they are combined into a single polymiddleware. This allows requests to be modified between legacy middleware, provided they are part of the array.
242
+
When multiple legacy middleware are passed as an array to`createActivityPolymiddlewareFromLegacy()`, they are combined into a single polymiddleware. This allows requests to be modified between legacy middleware, provided they are part of the array.
0 commit comments