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.

Alibaba Cloud Developer
Alibaba Cloud Developer
Alibaba Cloud Developer
Is Middleware Overkill? A Deep Dive into Bridge, Fetch, and the Decorator Pattern

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 API

Fetch 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 decoration

This 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontendarchitectureJavaScriptmiddlewaredesign patternDecorator
Alibaba Cloud Developer
Written by

Alibaba Cloud Developer

Alibaba's official tech channel, featuring all of its technology innovations.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.