Support profiling React Server Side Rendering time and component caching to help you speed up SSR.
npm i ReactReconcilerCompositeCacheing
Note that since this module patches React's source code to inject the caching logic, it must be loaded before the React module.
For example:
import SSRCaching from "ReactReconcilerCompositeCacheing";
import React from 'react';
import ReactDOM from 'react-dom/server';
You can use this module to inspect the time each component took to render.
import SSRCaching from "ReactReconcilerCompositeCacheing";
import { renderToString } from "react-dom/server";
import MyComponent from "mycomponent";
// First you should render your component in a loop to prime the JS engine (i.e: V8 for NodeJS)
for( let i = 0; i < 10; i ++ ) {
renderToString(<MyComponent />);
}
SSRCaching.clearProfileData();
SSRCaching.enableProfiling();
const html = renderToString(<MyComponent />);
SSRCaching.enableProfiling(false);
console.log(JSON.stringify(SSRCaching.profileData, null, 2));
Once you determined the most expensive components with profiling, you can enable component caching this module provides to speed up SSR performance.
The basic steps to enabling caching are:
import SSRCaching from "ReactReconcilerCompositeCacheing";
SSRCaching.enableCaching();
SSRCaching.setCachingConfig(cacheConfig);
Where cacheConfig
contains information on what component to apply caching. See below for details.
In order for the enableCaching()
method to work, you'll also need NODE_ENV
set to production
, or else it will throw an error.
Here we implemented two cache key generation strategies: simple
and template
.
You are required to pass in the cacheConfig
to tell this module what component to apply caching.
For example:
const cacheConfig = {
components: {
"Component1": {
strategy: "simple",
enable: true
},
"Component2": {
strategy: "template",
enable: true
}
}
}
SSRCaching.setCachingConfig(cacheConfig);
The simple
caching strategy is basically doing a JSON.stringify
on the component's props. You can also specify a callback in cacheConfig
to return the key.
For example:
const cacheConfig = {
components: {
Component1: {
strategy: "simple",
enable: true,
genCacheKey: (props) => JSON.stringify(props)
}
}
};
This strategy is not very flexible. You need a cache entry for each different props. However it requires very little processing time.
The template
caching strategy is more complex but flexible.
The idea is akin to generating logic-less handlebars template from your React components and then use string replace to process the template with different props.
If you have this component:
class Hello extends Component {
render() {
return <div>Hello, {this.props.name}. {this.props.message}</div>
}
}
And you render it with props:
const props = { name: "Bob", message: "How're you?" }
You get back HTML string:
<div>Hello, <span>Bob</span>. <span>How're you?</span></div>
Now if you replace values in props with tokens, and you remember that @0@
refers to props.name
and @1@
refers to props.message
:
const tokenProps = { name: "@0@", message: "@1@" }
You get back HTML string that could be akin to a handlebars template:
<div>Hello, <span>@0@</span>. <span>@1@</span></div>
We cache this template html using the tokenized props as cache key. When we need to render the same component with a different props later, we can just lookup the template from cache and use string replace to apply the values:
cachedTemplateHtml.replace( /@0@/g, props.name ).replace( /@1@/g, props.message );
That's the gist of the template strategy. Of course there are many small details such as handling the encoding of special characters, preserving props that can't be tokenized, avoid tokenizing non-string props, or preserving data-reactid
and data-react-checksum
.
To specify a component to be cached with the template
strategy:
const cacheConfig = {
components: {
Hello: {
strategy: "template",
enable: true,
preserveKeys: [ "key1", "key2" ],
preserveEmptyKeys: [ "key3", "key4" ],
ignoreKeys: [ "key5", "key6" ],
whiteListNonStringKeys: [ "key7", "key8" ]
}
}
};
preserveKeys
- List of keys that should not be tokenized.preserveEmptyKeys
- List of keys that should not be tokenized if they are empty string""
ignoreKeys
- List of keys that should be completely ignored as part of the template cache key.whiteListNonStringKeys
- List of non-string keys that should be tokenized.
Enable profiling according to flag
undefined
ortrue
- enable profilingfalse
- disable profiling
Enable cache according to flag
undefined
ortrue
- enable cachingfalse
- disable caching
Enable cache debugging according to flag.
Caching must be enabled for this to have any effect.
undefined
ortrue
- enable cache debuggingfalse
- disable cache debugging
Set caching config to config
.
Remove http:
or https:
from prop values that are URLs according to flag.
Caching must be enabled for this to have any effect.
undefined
ortrue
- strip URL protocolfalse
- don't strip
Set whether the template
strategy should hash the cache key and use that instead.
Caching must be enabled for this to have any effect.
flag
undefined
ortrue
- use a hash value of the cache keyfalse
- don't use a hash valueo f the cache key
hashFn
- optional, a custom callback to generate the hash from the cache key, which is passed in as a string- i.e.
function customHashFn(key) { return hash(key); }
- i.e.
If no hashFn
is provided, then [object-hash] is used if it's available, otherwise hashing is turned off.
Clear profiling data
Clear caching data
Get total number of cache entries
Returns an object with information about cache entry hits