- Notifications
You must be signed in to change notification settings - Fork34
Optimize React SSR with profiling and component caching
License
electrode-io/electrode-react-ssr-caching
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Support profiling React Server Side Rendering time and component caching to help you speed up SSR.
npm i electrode-react-ssr-cachingNote that since this module patches React's source code to inject the caching logic, it must be loaded before the React module.
For example:
importSSRCachingfrom"electrode-react-ssr-caching";importReactfrom'react';importReactDOMfrom'react-dom/server';
You can use this module to inspect the time each component took to render.
importSSRCachingfrom"electrode-react-ssr-caching";import{renderToString}from"react-dom/server";importMyComponentfrom"mycomponent";// First you should render your component in a loop to prime the JS engine (i.e: V8 for NodeJS)for(leti=0;i<10;i++){renderToString(<MyComponent/>);}SSRCaching.clearProfileData();SSRCaching.enableProfiling();consthtml=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:
importSSRCachingfrom"electrode-react-ssr-caching";SSRCaching.enableCaching();SSRCaching.setCachingConfig(cacheConfig);
WherecacheConfig contains information on what component to apply caching. See below for details.
In order for theenableCaching() method to work, you'll also needNODE_ENV set toproduction, or else it will throw an error.
SSR component caching was first demonstrated inSasha Aickin's talk.
His demo requires each component to provide a function for generating the cache key.
Here we implemented two cache key generation strategies:simple andtemplate.
You are required to pass in thecacheConfig to tell this module what component to apply caching.
For example:
constcacheConfig={components:{"Component1":{strategy:"simple",enable:true},"Component2":{strategy:"template",enable:true}}}SSRCaching.setCachingConfig(cacheConfig);
Thesimple caching strategy is basically doing aJSON.stringify on the component's props. You can also specify a callback incacheConfig to return the key.
For example:
constcacheConfig={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.
Thetemplate 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:
classHelloextendsComponent{render(){return<div>Hello,{this.props.name}.{this.props.message}</div>}}
And you render it with props:
constprops={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 toprops.name and@1@ refers toprops.message:
consttokenProps={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 preservingdata-reactid anddata-react-checksum.
To specify a component to be cached with thetemplate strategy:
constcacheConfig={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
undefinedortrue- enable profilingfalse- disable profiling
Enable cache according to flag
undefinedortrue- enable cachingfalse- disable caching
Enable cache debugging according to flag.
Caching must be enabled for this to have any effect.
undefinedortrue- enable cache debuggingfalse- disable cache debugging
Set caching config toconfig.
Removehttp: orhttps: from prop values that are URLs according to flag.
Caching must be enabled for this to have any effect.
undefinedortrue- strip URL protocolfalse- don't strip
Set whether thetemplate strategy should hash the cache key and use that instead.
Caching must be enabled for this to have any effect.
flagundefinedortrue- 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 nohashFn is provided, thenfarmhash 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
Built with ❤️ byTeam Electrode @WalmartLabs.
About
Optimize React SSR with profiling and component caching
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors8
Uh oh!
There was an error while loading.Please reload this page.