Is Middleware Overkill? A Deep Dive into Bridge, Fetch, and the Decorator Pattern
This article examines middleware as a front‑end design pattern, presents simple compose implementations, analyzes real‑world cases like Bridge and Fetch, compares middleware with the decorator pattern, and proposes API design guidelines to balance flexibility and maintainability.
Introduction
Middleware is often regarded as a design pattern in front‑end development and can serve as the foundation of an application’s architecture. This article explores the advantages and disadvantages of middleware, shows simple implementations, and discusses concrete examples such as Bridge and Fetch.
Simple Middleware Example
const compose = (middlewares) => {
const reduce = (pre, cur) => {
if (pre) {
return (ctx) => cur(ctx, pre);
} else {
return (ctx) => cur(ctx, () => ctx);
}
};
return [...middlewares].reverse().reduce(reduce, null);
};The composed function executes each middleware in order, allowing each to run code before, after, or conditionally skip the next middleware.
Onion Model Illustration
The execution order follows an outer‑to‑inner then inner‑to‑outer flow:
middleware1 → middleware2 → middleware3 → middleware2 → middleware1.
Practical Use Cases
Bridge uses plugins to inject APIs, where each plugin provides a name, an API name, and a middleware. The Bridge aggregates plugins with the same API name and composes their middleware.
bridge.API('APINAME', handler);
// or
bridge.APINAME = handler;Middleware can be applied globally or per API:
bridge.use(middleware); // all APIs
bridge.use('APINAME', middleware); // specific APIFetch Example
Fetch adopts a similar middleware approach, allowing a common middleware and adaptor‑specific middleware to be registered:
fetch.use(commonMiddleware);
fetch.use('adaptor-json', [middleware]);
fetch({ ...requestConfig, adaptor: 'adaptor-json' });This design keeps the request interface consistent while delegating request‑type specifics to middleware.
Relation to the Decorator Pattern
The middleware chain behaves like the decorator pattern: each middleware wraps the next, adding behavior without altering the original function’s interface. This similarity is illustrated in classic decorator examples such as coffee pricing.
Design Recommendations
To reduce API uncertainty and maintenance cost, define a clear main handler for each API and treat middleware as optional decorations:
bridge.API('APINAME', handler);
bridge.use(middleware); // optional decorationThis makes the primary logic explicit while still allowing shared concerns to be handled by middleware.
Conclusion
Middleware can be a powerful tool for sharing cross‑cutting concerns, but it should be used as a decorator to a well‑defined core function. Clear API contracts and disciplined use of middleware help balance flexibility with understandability and maintainability.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alibaba Cloud Developer
Alibaba's official tech channel, featuring all of its technology innovations.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
