Next.js: Component-based server-side caching strategy

Created on 19 Feb 2017  路  5Comments  路  Source: vercel/next.js

Internal, opt-in component SSR caching/memoization instead of page caching.

react-dom-stream/lru-render-cache by @aickin

First, you must instantiate a cache object and pass it to either renderToString or renderToStaticMarkup as the cache attribute on the optional options argument. Currently, there is only one implementation of a cache, LRURenderCache, contained in the module react-dom-stream/lru-render-cache. It takes in an options object that has one attribute, max, which specifies the maximum number of characters in the cache. It looks like this:

import ReactDOMStream from "react-dom-stream/server";
import LRURenderCache from "react-dom-stream/lru-render-cache";

// create a cache that stores 64MB of text.
const myCache = LRURenderCache({max: 64 * 1024 * 1024});

app.get('/', (req, res) => {
    ReactDOMStream.renderToStaticMarkup(<Foo prop={value}/>, {cache: myCache}).pipe(res);
});

Second, you need to have your components opt in to caching by implementing a method called componentCacheKey, which returns a single String representing a useable cache key for that component's current state. The String returned by componentCacheKey must include all inputs to rendering so that it can be used as a cache key for the render. If componentCacheKey leaves out some of the inputs to rendering, it's possible that you will get cache collisions, and you will serve up the wrong content to your users. Here's an example of a correct implementation:

import React from "react"

export default class CacheableComponent extends React.Component {
    render() {
        return <span>Hello, ${this.props.name}!</span>;
    }

    componentCacheKey() {
        // the name prop completely specifies what the rendering will look like.
        return this.props.name;
    }
}

So next.js/examples/data-fetch/index.js becomes:

import React from 'react'
import Link from 'next/prefetch'
import 'isomorphic-fetch'

export default class MyPage extends React.Component {
  static async getInitialProps () {
    // eslint-disable-next-line no-undef
    const res = await fetch('https://api.github.com/repos/zeit/next.js')
    const json = await res.json()
    return { stars: json.stargazers_count }
  }

  render () {
    return (
      <div>
        <p>Next.js has {this.props.stars} 猸愶笍</p>
        <Link href='/preact'><a>How about preact?</a></Link>
      </div>
    )
  }

  componentCacheKey () {
    return this.props.stars;
  }
}

Most helpful comment

Any updates on this?

All 5 comments

I think this one follows some similar ideas.
I think we can do something similar by simply using a current setup we've without doing any core Next.js modifications.

And I'd really like to have some examples with this.

I have an example of component-level caching in #2279, using Rapscallion.

Any update on this. Are you guys planning to bring support anytime soon? Currently, I couldn't find any way to implement component-based caching.

like: https://github.com/rookLab/react-component-caching

Any updates on this?

Was this page helpful?
0 / 5 - 0 ratings