✓ Email copied to clipboard
← BACK TO JOURNAL

Why We Stopped Using React for Creative Artifacts

ADVERTISEMENT Google AdSense
Why We Stopped Using React for Creative Artifacts

The React Tax

For years, we leaned on React as our default. It felt safe. When you need to build interfaces that scale, the ecosystem is a gravitational pull you rarely resist. But our work isn't traditional web application development. We aren't building CRUD dashboards or e-commerce checkouts. We build high-fidelity, shader-heavy creative artifacts that need to maintain 60fps while handling complex memory management. Last year, after chasing a 400ms lag spike caused by a bloated reconciliation tree in a 3D visualizer, we finally hit our breaking point.

The DOM is Already Enough

Standard advice suggests you need a virtual DOM to manage complexity. This is fundamentally wrong for our use case. When we stripped out React and moved to native Web Components, we reclaimed the actual browser engine. We stopped treating the DOM as an expensive object that needs to be diffed and started treating it as a literal tree of nodes that we control directly. The performance gain wasn't just incremental; it was foundational.

The most expensive code in your project is the code you imported from someone else's dependency tree.

Getting Back to the Metal

Moving to Custom Elements and Shadow DOM forced us to write cleaner code. Without the safety net of hooks, we had to get disciplined with lifecycle management. When we initialize a WebGL context, we don't want a framework trying to synchronize state on every frame. We want raw access. Using connectedCallback and disconnectedCallback, we now manage our memory buffers with surgical precision.

class ShaderArtifact extends HTMLElement {
  connectedCallback() {
    this.gl = this.querySelector('canvas').getContext('webgl2');
    this.initPipeline();
  }
  disconnectedCallback() {
    this.cleanup();
  }
}
customElements.define('shader-artifact', ShaderArtifact);

Why This Matters for Design Systems

Beyond performance, there is the issue of longevity. Frameworks churn. Every two years, a major version arrives to break your patterns or force a migration. By committing to the Web Components standard, we are building artifacts that don't expire. A component built for the browser five years ago will still execute in the browser five years from now. This isn't just an engineering decision; it’s an architectural stance against the built-in obsolescence of the modern JS ecosystem.

The Trade-offs We Made

  • State management: We replaced Redux/Zustand with a simple pub-sub event bus using native CustomEvent APIs.
  • Styling: We abandoned CSS-in-JS. Shadow DOM encapsulates our styles naturally, allowing us to use vanilla CSS without the overhead of styled-components.
  • DX: We lost hot-module replacement (HMR) efficiency, but we gained a codebase that is easier to debug because the stack traces don't contain sixteen layers of framework abstraction.

The Provocation

If your project doesn't require complex data synchronization between three different micro-services, why are you paying the 150KB tax for a framework? The browser is a powerful, capable environment. Stop fighting it. Stop wrapping it in layers of abstraction that only serve to slow down your render loop. Build once, build native, and watch your frame times drop to near zero.

ADVERTISEMENT Google AdSense
// DISCUSSION TERMINAL

READER ESSAY DISCUSSIONS (0)

Share your architectural perspectives, technical notes, or critique.

LEAVE A THOUGHT Markdown & clean text supported
💬

No discussions recorded yet.

Be the first to spark the dialogue on this essay.

← PREVIOUS ESSAY

Why We Abandoned the React Industrial Complex for Creative Web Components

NEXT ESSAY →

Death to the Smooth Edge: Restoring Friction to the Digital Interface