React / Next.js / WHATWG
React: Origins and Initial Use-case
Despite its near ubiquitous usage for all manner of front-end development scenarios these days, Facebook initially developed React as a response to a very specific problem: UI state was becoming unmanageable in large, highly interactive applications. React's original design introduced several (at the time) radical ideas:
This design optimized for developer reasoning, although it was not without its tradeoffs: React sacrificed the separation of concerns that had been part and parcel of the best practices of web development up until that time.
This radical design also met with initial pushback from some in the developer community, such as:
- "The virtual DOM is slow."
- "JSX is ugly."
- "This isn't real MVC."
React Matures
Once React was open-sourced, its adoption spread beyond Facebook. This included its use in React Native, the development of Redux state management, and many community libraries to fill gaps, as the core of React left routing, data fetching, build pipelines, and state management opinions out of the picture.
This overall approach positioned React as a rendering engine, not an application framework, which presaged the need for meta frameworks such as Next.js.
Before the advent of Next.js, React was rewritten (known as Fiber) to solve a fatal flaw in its initial design: rendering had up until then been synchronous and blocking. The Fiber rewrite added a scheduling system, rendering units-of-work, and a priority queue for rendering updates.
The tradeoff of the Fiber rewrite was vastly increased internal complexity of the core React codebase...although in keeping with the theme of React this complexity was hidden to preserve the user-facing mental model.
After the Fiber rewrite, hooks and function components were introduced to tackle the confusing lifecycle methods of class components. Hooks helped colocate state, side effects, and context, while encouraging reuse. However, they came with the tradeoff of strict rules, and potentially error-prone dependency arrays.
The Rise of Next.js
A meta-framework like Next.js was needed to create shared conventions around routing, code splitting, server rendering, and build complexity. It's crucial to note that these were all integration problems, not problems with the core React codebase. Along the way, Next.js evolved to accommodate React Server Components with the App Router. The use of RSCs re-framed the bias toward heavy clients and single page apps:
The gains of RSCs and the App Router in terms of performance and fine-grained caching come with a tradeoff: the learning curve can be steep, developers have to adopt the mental model of async-everywhere, and debugging tools are still evolving.
How Does the WHATWG Compare?
React abstracted DOM mutations, events, state management, and UI lifecycle because Web APIs provided by the WHATWG (Web Platform) spec were fragmented, and browser inconsistencies were historically very common. However, the Web Platform has caught up in some key ways:
Whether the ecosystem gravity of React will outweigh the Web Platform is a matter of contention in the web development community. Although, the trajectory of React apps shipping less and less JavaScript to the browser due to RSCs does seem to align with the ethos of the Web Platform. In terms of Next.js, providing predictable caching, fast local dev, edge execution, and server observability does position the meta-framework to be the defacto choice for React web apps.
Summary (Key Points to Remember)
React
- A UI scheduling and composition engine
- Optimized for human reasoning
- Increasingly server-first
Next.js
- A production-grade orchestration layer
- Opinionated defaults around React’s future
- Deep integration with hosting primitives
Web Platform
- Catching up rapidly
- Influencing React development
- Likely to absorb some responsibilities back over time