There are many game engines in the world: Unreal Engine, Unity Engine, Godot Engine, Cry Engine, and more.
What do these game engines have in common? Customizability. Different games have different requirements and need specific features to achieve their goals. It’s difficult to provide every possible feature in a single program, which is why many engines allow developers to modify the source code and build their own custom features. Customization is an essential part of these engines.
Now, let’s shift back to frontend development. React is one of the most popular frameworks in this space. But, just as modifying the engine is common in game development, is it as common to modify React's internal source code in frontend development? This simple question reveals a lot about what we're really pursuing and highlights the difference in direction between modern frontend development and other fields.
React is a framework that is nearly impossible to modify. You are encouraged to use React as is, and it's not intended for developers to customize its internal architecture or rendering pipeline. Therefore, using React means you must solve all your requirements within the confines of React’s structure. But the world is full of diverse requirements, and not all of them can be solved within React’s framework.
"There’s no such thing as a free lunch."
"There’s no tool that can do everything."
React is just one development tool, and it has its limits.
The primary reason developers use React is productivity. React was created with the question, "How can we develop DOM components more efficiently in web development?" At the center of React’s approach is the DOM. Just like how automated features generally mean a lack of customization, the "productivity" they talk about often means "you cannot modify the rendering loop tightly coupled with the browser through the virtual DOM."
The first major issue with React is the DOM. Not everything revolves around the DOM, and not every program operates solely around it. Yet, React places the DOM at the core of its philosophy. The JSX syntax, where each component returns something "HTML Element Like," clearly reflects this mindset.
The second issue is the virtual DOM. Here’s how the virtual DOM works:
- The DOM is inherently slow.
- To mitigate this, React introduces a faster internal logic.
- This logic creates an object that copies the shape of the actual DOM tree, known as the virtual DOM. Whenever rendering occurs, React finds the changes using this virtual DOM and only updates those parts.
- To implement this system, DOM updates must always go through the root DOM element.
- The virtual DOM works seamlessly with React’s internal operations.
The question is, why would HPSE adopt such a system in the first place? Besides the worry that this rendering approach cannot address various HPSE requirements, the bigger concern is its lack of actual utility in this context.
In HPSE, DOM components can be managed at the class level. When an instance is created, its top-level div DOM reference is stored as a member variable. The private methods of the instance can either directly manipulate the DOM reference or use querySelector() to access it. In most cases, this would be faster than comparing the entire DOM tree.
Using the virtual DOM is just a way to identify changes, but if you already have the changes stored internally within your instance, searching for them again is redundant. Once the DOM element is updated, the browser will still trigger ReFlow and RePaint, so there’s no difference in performance afterward.
The ultimate issue lies in React’s "internal operations." What exactly are these internal operations? There's a lack of detailed documentation or information, and most frontend developers don’t fully understand them either. The browser client already operates within the abstraction layer of the browser itself, making it vulnerable to various challenges. React’s opaque and unmodifiable internal processes only exacerbate this vulnerability.
Changes to components in React must go through the virtual DOM, and the virtual DOM is managed by the Fiber architecture, which follows specific priority rules. However, there is little documentation on how to customize React’s internal functions to meet the real-time performance or precision timing demands of HPSE. It feels like developing a AAA game with an engine that can’t be customized.
"Why bother?"
It’s a question that keeps coming up.
React is so tightly coupled internally that even if you wanted to modify it, you couldn’t. It was never designed with that purpose in mind. Moreover, the strong coupling of rendering and state updates makes React unsuitable for HPSE projects, where non-visual components like data or 3D elements must be managed alongside DOM elements.
In HPSE, the timing of event calls and memory unmounts may not be tied to individual components, but React enforces this component-based structure, making it difficult to handle such requirements. React’s design, where state changes in components can affect the entire rendering tree, also conflicts with HPSE’s need to minimize or control such impacts.
Libraries like React Three Fiber (R3F) allow you to create instances like Mesh or Scene using an "HTML Element Like" syntax, but that’s simply Three.js adapted to React’s structure. The high level of coupling within React only worsens the issue of unmodifiable internals.
React’s event handling approach is also problematic. React uses a synthetic event system to ensure browser compatibility and consistency in event handling. However, by adding an abstraction layer to event processing, this system limits the fine-grained control over event loops and timing needed in HPSE, making it difficult to implement essential optimizations.
These issues arise because React’s design philosophy is fundamentally different from the goals of HPSE. React wasn’t built with HPSE in mind; it was designed to optimize the development of standard web clients. If React had pursued a similar direction to HPSE, its features would have been vastly different, and there would be a case for adopting it in HPSE development. But since their goals are so divergent, they inevitably part ways.
This isn’t to say that everything about React, like routing or useEffect, is bad. In fact, most of these features can be implemented using standalone JavaScript modules or code. Unlike React, general JavaScript modules don’t enforce specific pipelines or rules on projects. Moreover, if they are open-source, you can modify their internals to suit your needs.
Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.
Copyright© 2022 湘ICP备2022001581号-3