Why Frontend Frameworks Fail and How to Build Better Architecture

Modern front‑end frameworks like Vue and React have sparked a cult‑like devotion that often obscures deeper issues; this article examines the resulting complexity, argues that developers—not tools—are the key variable, and presents a layered, composable architecture with code examples to improve maintainability.

Alibaba Cloud Developer
Alibaba Cloud Developer
Alibaba Cloud Developer
Why Frontend Frameworks Fail and How to Build Better Architecture

Frontend Development Dilemma

Two "cults" dominate the front‑end world—Vue and React. Their followers often view their own framework as the ultimate truth, overlooking the fact that no framework is perfect. The real variable is the developer, whose skills and decisions ultimately determine code quality, project lifespan, and system complexity.

Is the Framework to Blame?

The "worship" of modern front‑end frameworks makes development more complex and degrades code quality. While frameworks like Vue and React solve view‑layer challenges, they also introduce a proliferation of tools, state‑management libraries, routing solutions, and component collections that can overwhelm teams and shorten software lifecycles.

Frameworks are designed to address UI rendering, not business logic. Over‑reliance on them leads to "small problems made big"—the tendency to solve every issue with the framework instead of evaluating the underlying problem.

Proposed Architecture Solution

To mitigate these issues, a layered, composable architecture is suggested, inspired by MVP and DDD principles. The architecture consists of three layers:

Data Layer (Model) : Handles raw data entities, similar to backend domain models.

Logic Layer (Presenter) : Encapsulates business logic and coordinates between models and views.

View Layer (View) : Pure UI rendering, receiving state from the presenter.

Each layer should be built through composition rather than inheritance, keeping dependencies unidirectional to reduce coupling.

Code Example: Hook Usage

function useUser(id) {
  const { data, error } = useSWR(`/api/user/${id}`, fetcher);
  return {
    user: data,
    isLoading: !error && !data,
    isError: error,
  };
}

The hook demonstrates a shift from component‑centric thinking to data‑flow‑centric logic, separating fetching concerns from UI rendering.

Full Architecture Example (Scheme A)

Scheme A targets medium‑size pages with up to 20 sub‑modules. It separates concerns as follows:

Model Example

export default {
  namespace: 'PortalGoodModel',
  state: { pageNum: 1, pageSize: 10, hasNextPage: true, goodsData: [] },
  reducers: {
    updateGoodsData(state, payload) { /* update data */ }
  }
};

Presenter Example

export default class PortalPresenter {
  getPageData(obj) {
    this.$PortalLocationPresenter.onLocation({
      success: () => this.$PortalGoodsPresenter.fetchData(obj)
    });
  }
}

Location Presenter

export default class PortalLocationPresenter {
  async getInfo() {
    const locationInfo = await this.dispatch({type: 'PortalLocationModel/updateInfo'});
    return locationInfo;
  }
  async onLocation(obj) {
    const { adCode, userAdCode, longitude, gpsValid } = await this.getInfo();
    if (!(adCode && userAdCode && longitude) || !gpsValid) {
      this.dispatch({type: "PortalLocationModel/updateLocationStatus", value: 'error'});
      obj?.fail();
    } else {
      this.dispatch({type: "PortalLocationModel/updateLocationStatus", value: 'success'});
      obj?.success();
    }
  }
}

Goods Presenter

export default class PortalGoodsPresenter {
  async fetchData(obj) {
    const requestParams = utils.getRequestParams({pageData: this.$page.props, location});
    const res = await fetch(requestParams);
    if (res.code !== 1) {
      obj?.fail();
    } else {
      const result = this.processResult(res);
      this.dispatch({type: 'PortalGoodModel/updateGoodsData', ...result});
      obj?.success();
    }
  }
}

View Example

{
  state(state) { return { ...state, noResultPageVisible: state.PortalGoodModel.goodsData.length } },
  ready() { this.getPageData(); },
  getPageData(info = {}) {
    this.$presenter.getPageData({
      type: info.type,
      fail(errorInfo) {
        if (errorInfo.type === 'locationError' && info.from === 'onErrorRetry') {
          utils.toast('请开启定位');
        }
      }
    });
  }
}

Conclusion

Modern front‑end frameworks have driven significant progress in UI development, but blind worship leads to unnecessary complexity and reduced code quality. Developers must adopt a layered, composable architecture, focus on separating view from business logic, and continuously refine their skills to achieve sustainable, maintainable front‑end systems.

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.

frontendarchitecturebest practicesframeworkscode organization
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.