Skip to content

Commit efb671e

Browse files
committed
Add more content
1 parent 77c0016 commit efb671e

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

docs/MIDDLEWARE.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
Middleware serves as a core element of Web Chat's architecture, enabling deep and cascaded UI customization.
44

5+
Middleware operates in a cascading sequence, where the execution order plays a critical role. An upstream middleware can influence whether and how the downstream middleware renders. Middleware can perform the following operations:
6+
7+
- Add new UI
8+
- Remove existing UI
9+
- Replace existing UI
10+
- Decorate existing UI
11+
512
<!-- TODO: More docs -->
613

714
## Recipes
@@ -125,8 +132,57 @@ const polymiddleware = [
125132
];
126133
```
127134

135+
### Mixing polymiddleware with legacy middleware
136+
137+
> Notes: legacy middleware is deprecated and will be removed on or after 2027-08-16.
138+
139+
The following code snippet a legacy activity middleware followed by polymiddleware.
140+
141+
```tsx
142+
const MyActivity = ({ request }) =>
143+
<div className="polymiddleware">{request.activity.text}</div>
144+
145+
const polymiddleware = [
146+
// Legacy activity middleware
147+
createActivityPolymiddlewareFromLegacy(() => next => request => {
148+
const child = next(request);
149+
150+
return () => <div className="legacy">{child?.()}</div>;
151+
},
152+
// Polymiddleware handling activity request
153+
createActivityPolymiddleware(next => request => activityComponent(MyActivity, { request }))
154+
]
155+
```
156+
157+
For a message activity of "Hello, World!", it will render:
158+
159+
```html
160+
<div class="legacy">
161+
<div class="polymiddleware">Hello, World!</div>
162+
</div>
163+
```
164+
128165
## Behaviors
129166
167+
### When will legacy middleware removed?
168+
169+
We started the polymiddleware in 2025-08-16. Based on our 2-year deprecation rule, legacy middleware will be removed on or after 2027-08-16. The following table should deprecation dates for various legacy middleware.
170+
171+
| Legacy middleware | Remove on or after |
172+
| ---------------------------- | ------------------ |
173+
| Activity | 2027-08-16 |
174+
| Activity status | (TBD) |
175+
| Attachment | (TBD) |
176+
| Attachment for screen reader | (TBD) |
177+
| Avatar | (TBD) |
178+
| Card action | (TBD) |
179+
| Group activities | (TBD) |
180+
| Scroll to end button | (TBD) |
181+
| Send box | (TBD) |
182+
| Send box toolbar | (TBD) |
183+
| Toast | (TBD) |
184+
| Typing indicator | (TBD) |
185+
130186
### Polymiddleware vs. legacy middleware
131187
132188
Polymiddleware is a unification of multiple legacy middleware into a single prop.
@@ -135,6 +191,33 @@ Previously, legacy middleware would sometimes return a render function and other
135191
136192
Polymiddleware enforces immutability of requests. Unlike legacy middleware, an upstreamer in polymiddleware is prohibited from passing a modified request to a downstreamer.
137193
194+
### Why we think polymiddleware is better?
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.
197+
198+
- In other languages, middleware is called "chain of responsibility"
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
203+
- 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
206+
- 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"
210+
- Props and hooks are render-time variable and is for "how to render the UI"
211+
- All UI-rendering middleware should share same API signature
212+
- Card action and group activity middleware could be exempted because they are not UI-rendering
213+
- 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
217+
- "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
220+
138221
### Polyfilling legacy middleware
139222
140223
Legacy middleware passed to deprecating props such as `activityMiddleware` will be polyfilled to polymiddleware after other polymiddleware passed via the `polymiddleware` prop.

0 commit comments

Comments
 (0)