
Is React 🚀 FAST, or React is 🐌 SLOW? It's super easy to answer this question, just a no brainer.
- React is fast. Full stop. React is fast when it could be fast: not displaying too much data, and not animating something in 60 frames per second. There is always afaster kid on the block(Svelte?), but React is fast enough almost for any case.
- React is slow. Another full stop. It's not a big deal to make it slow - inline 1000 SVGs and use React to render them all, or render 100 pages simultaneously on a Server Side.
In short - React is 👍 as a Client Side Library, but for Server Side Rendering - oh, it will 🔥 burn your CPU, and AWS bill. Not because it slow, but because everything has limits.
That's obvious - you cannot compare situations when ALL CPUs are working for a ONE customer sake (in browser), and the situating, when you have to render the same, but for a dozen clients simultaneously.
That's also obvious how to mitigate the problem - it was know for generation, and for react itself it’s the main idea around handling unneeded updates - memoization. Or, in terms of old school SSR - justcache.
Cache for small blocks, cache for big blocks, cache for pages, data and intermediate results. Cache as much as possible, and let render results of a one customer speed up render for another customer.
Caching is a well-known pattern, and always was saving a day! For decades! For everyone! Except for React.
React days
So, caching in React? Do you remember an API for it? No, you don’t. There isn’t any.
You still able to cacherenderToString
result - not a big deal, orcacherenderToNodeStream
asmxstbr did for Spectrum last year.
But do we need caching?
Yes - React 15 was REALLY SLOW, and React 16, even if it is much faster, still require some time to render the result.
Anything requires some time. Everything has requirements and limits.
Caching in React
As long as the problem existed, there were many devs, with acaching background(from previous experiences in different frameworks or languages) to solve it - new patterns and libraries emerged.
Rapscallion
Alternative to React-DOM. Our hero. Saved millions of CPU cycles. Was able to handle data loading on the component level, and caching the result as well.
Worked perfectly.Till React 16. Not worked after.
FormidableLabs / rapscallion
Asynchronous React VirtualDOM renderer for SSR.
Rapscallion
Overview
Rapscallion is a React VirtualDOM renderer for the server. Its notable features are as follows:
- Rendering isasynchronous and non-blocking.
- Rapscallion is roughly30% faster than
renderToString
. - It provides a streaming interface so that you canstart sending content to the client immediately.
- It provides a templating feature, so that you canwrap your component's HTML in boilerplate without giving up benefits of streaming.
- It provides acomponent caching API to further speed-up your rendering.
Table of Contents
Installation
Using npm:
$ npm install --save rapscallion
In Node.js:
const{ render, template}=require("rapscallion");// ...
API
render
render(VirtualDomNode) -> Renderer
This function returns a Renderer, an interface for rendering your VirtualDOM element. Methods are enumerated below.
Renderer#toPromise
…Another great tool for Component Level caching. Another tool which hacks into React and trying change the way it works. Yet another tool whichdoes not works with React 16.
electrode-io / electrode-react-ssr-caching
Optimize React SSR with profiling and component caching
react-ssr-optimization
A magic system formemoization andtemplatenization from Walmart Labs. Was once broken during React 14-15 migration, anddidn't get React 16 support.
walmartlabs / react-ssr-optimization
React.js server-side rendering optimization with component memoization and templatization
React-component-caching
TLDR: Actually aworking one!
rookLab / react-component-caching
Speedier server-side rendering with component caching in React 16
CitingSpeedier Server-Side Rendering in React 16 with Component Caching
Sasha Aickinintroduced and demoed component caching in a 2016 talk on ways to speed up server-side rendering. Soon afterwards, Walmart Labs created acomponent caching library with a profiling feature to time renders. The idea received attention atReact Amsterdam last year, and it has surfaced in discussions on Github. A component caching API was also incorporated in Formidable’s React server renderer,Rapscallion.
With the release of React 16 last September, many of these efforts have been due for a reboot. React has improved the speed of its server-side rendering methods and now offers two streaming methods. We were curious if it was possible to harness the power of component caching with these new and improved methods. So we builtReact Component Caching to give developers the ability to do just that.
But, you know, this library is quite complex inside, and would be broken on next React release - 100%. And user-facing API is also quite complex... But it's working, working with memcache or other caching libraries and was a single saviour... until today.
React-Prerendered-Component
Then - let me introduce another approach to a component level caching in React, which willnever be broken. Never by design.
import{CachedLocation,NotCacheable}from'react-prerendred-component';constMyCachedComponent=()=>(<CachedLocationcacheKey="MyCachedComponent">anycodeyouwant</CachedLocation>);// component like this shall not be cached.constSomeNonPureImportantComponent=()=>(<NotCacheable>hey{global.userName}</NotCacheable>);
Simple? Easy? How does it work?
How it works
CachedLocation
will wrap your component with<x-cached-store>{children}<x-cached-store>
- result of
renderToString
would be analyzed for such markers, and marker's content would be moved into the cache. ForrenderToStream
the same is working viatransform streams
. - if
key
was present in the store, thenCachedLocation
would render<x-cached-restore-key />
, and the same post-filter would replace this text by the stored value.
This works on HTML/stream transformation level, anddon't rely on ANY React internals.
The same isworking for Client Side!CachedLocation
will just wrap your data with adiv
and store/restore data usingdangerouslySetInnerHTML
. For example, you mightcache those big SVGs, I was mentioning in the beginning.
<CachedLocationcacheKey="svg-fileName">// react component first time, just a string second.<MySVRGComponent/></CachedLocation>renderToString(...);// - first render, cache is empty, making a full render// <x-cached-store-1><svg..../></x-cached-store-1>// - cache stored, extra tags removed// <svg .../>renderToString(...);// - second render, cache exists - restore entity// <x-cached-restore-1/>// - we know what to restore// <svg ...
While
CachedLocation
is adding extra tags during the render - they would be removed later. It's a transparent process!
It is allpure HTML based solution, which worksafter React did the job.
XSS my friend?
So - let's recall it once again -CachedLocation
will put sometag
in result HTML and some dummy(it is) RegEx will do the rest.
What if your dear customer will do the same? What if the sametag
would be found in JSON, script and visa versa? Of course,it will blow :P
So - in the real world this library would not use so obvious tag names, but will usenanoid to generate unique tag names every render. So - no XSS and no false positives are possible, relax.
<x-cached-supersecretstring-11/>// it's "safe"
The only, hm, problem here - now caches, generated in different threads, are not compatible with each other, and so in case of distributed cache you have to specifysuper-secret-seed
by your own.
Templatezation
It's a long, and probably not quite a correct, term stand for lessvariative memoization.
For example - header ofdev.to
contains your avatar, but everything else is the same - you may "template it" into the static and cached<Header/>
. What would happen if you will cache header in a per-user basis? Well, cache is not infinite.
Picture fromScaling React Server-Side Rendering.
Instead of having 100500 different<Button>unuqieText</Button>
you might just have<Button>#text#</Button>
- so you will memoize only complex html markup, adding some "variables" using simplereplace
methods.
While usingstring replaces is not quite safe, this library gives you a few components toinject Placeholders, which uses Context API to drill down the props, and requires just a small code style changes to be used.
constUserHeader=()=>(<div>.....<Placeholdername="userName"/>....</div>)renderToString(<CacheLocationvariables={{userName:'Joe'}}><UserHeader/></CacheLocation>);// <x-cached-store-1 userName="Joe">....{x-cached-placeholder-userName}...</x-cached-store-1>renderToString(<CacheLocationvariables={{userName:'Jack'}}><UserHeader/></CacheLocation>);// <x-cached-restore-1 userName="Jack"/>// ....{x-cached-placeholder-userName}...// ....Jack...
This is a very powerful tactic to reduce memory usage and skyrocket your application viatransforming your brand new React App to old school template engine.
Which is just 🚀VERY🚀FAST🚀.
PS: This could give you sub-millisecond SSR,react-component-caching
have proved it.
PPS: But this is not workingyet for the client-side cache. Using variables for CSR caching will disable caching.
Another name of this technique is cacheinterpolation
, and if you want to TRULY understand everything behind fragment caching - readThe Article.
Where is the cache?
Another cool moment this approach is acache
. A simple React 16/Suspense compatible cache model.
- synchronously
get
the cache - synchronously
set
the cache. - No cache available? - Throw a promise!
You cannon usereact-cache, as long as it utilizes a different model (there is noset
), but any other cache, including in-memory orshared-memory ones - easy.
But not memcache, as long asasynchronius cache is not supported.
Prerendered component gives you the power of componentmemoization
, andtemplatization
both for Server and Client, and would not break in the future, just because it built that way - to never let you down.
Give it a try.
Or just think about it.
theKashey / react-prerendered-component
🤔Partial hydration and caching in a pre-suspense era
PS: By the way, react-prerendered-component was a hero for other article:
Top comments(6)

- LocationPalo Alto
- WorkEngineer at Trueclap
- Joined
Hello Anton , Very interesting article focusing on Cache. Have you checked Apollo Client to cache on client side. if you are using client side rendering then you can use Apollo client side cache along with graphQL.

That’s apples and oranges.
Apollo cache is aboutcaching data, and then using it to render a view.
This solution is aboutcaching view, but not the data.
You may mix them together, and, get data and view caching simultaneously.
Even more - view layer caching will cut off all nested graphQL connectors and, yeah, 🦄🎉🔥.
TLDR - no, Apollo cache has nothing with this one.

- LocationPalo Alto
- WorkEngineer at Trueclap
- Joined
Thanks for correcting on this. How does caching view works? Is this more specific to server side rendering? I have no knowledge about server side rendering and never came across caching view on client side implementation. All my implementations are using reactJS and GatsbyJS to render on client side.

That would take a while, but readScaling React Server-Side Rendering/Component Caching.

As the old quote said: "There're two things that are hard in Computer Science, it's naming and cache invalidation".
Caching is not hard.
Invalidate cache is hard.

Not only invalidation. Let imagine - you don't have a cached value, so you have generate it. Obviously, that decision would be made in 10 threads at 10 servers simultaneously :)
Cache invalidation is not a real problem - cache management, oh dear, is.
For further actions, you may consider blocking this person and/orreporting abuse