Show HN: Forked styled-components with optimizations (40% faster for Linear)

4 kmelve 1 9/11/2025, 5:07:03 PM github.com ↗
Hey HN! We forked styled-components after it entered maintenance mode because our production apps (and many others) can't migrate overnight.

Backstory: We submitted PR #4332 (https://github.com/styled-components/styled-components/pull/...) to styled-components in July 2024 with React 18 optimizations. When maintenance mode was announced, we turned that PR into this fork.

What we fixed: - Added React 18's useInsertionEffect - Rewrote streaming SSR for React 19 - Replaced ES5 output with modern JS - Optimized array operations with native flatMap - Fixed Next.js App Router to work without 50+ lines of boilerplate

Linear tested it and saw 40% faster initial renders with zero code changes.

How to try it: npm install @sanity/styled-components@npm:styled-components

Or for React 19: npm install @sanity/css-in-js@npm:styled-components

Benchmark tool to test yourself: https://css-in-js-benchmarks.sanity.dev/

We named it "last-resort" because that's what it is. We're not trying to maintain styled-components long-term - we're actually migrating to vanilla-extract ourselves. This is just a performance bridge while teams migrate properly.

The React team recommends moving away from runtime CSS injection. We agree. But migrations take time, and production apps need to ship today.

Comments (1)

cocody · 52m ago
Some more context on why the PR doesn't make a dent in the existing benchmark suite: - existing benchmarking suite uses react 17 as the baseline, the new useInsertionEffect hook requires react 18. Additionally, the new hook plays a role in concurrent render scenarios also introduced by react 18, which the current benchmark wasn't testing. We made a new benchmark on react 19 in a worst case scenario that the new hook is designed to mitigate, we shared a recording of the before and after here https://github.com/styled-components/styled-components/pull/... with before and after links. = react 18 and later and its concurrent render mode uses cooperative scheduling techniques and tries to yield to the main thread and have your application stay responsive. You won't see a difference in flamecharts in the same way as typical perf issues, since the problem isn't that something is blocking main thread render and causing locks or fps drops necessarily. The problem is that background render takes much longer and risk hitting the deadline where it becomes sync. - it's notoriously difficult to write benchmarks that tap into concurrent mode behaviors in react, our own benchmark had to write css that escape the default styled components scoped selectors in order to get consistent bench results. - if it's the same speed as before in the react 17 benchmarks it means the new behavior and its fallback when outside of react 18 is working as intended and did not cause a regression. It's not reasonable for it to be significantly faster in all cases, the purpose is to prevent it from being extremely slow in Suspense, React.lazy, useTransition, useDeferredValue, <Activity mode="hidden">, startTransition, and other concurrent mode cases.