React-instantsearch: Add Server Side Rendering compatibilty

Created on 11 Apr 2017  ·  10Comments  ·  Source: algolia/react-instantsearch

Use case

When using https://zeit.co/blog/next you can use React InstantSearch but won't benefit of a good SEO (having all the results since the first rendering).
See: https://github.com/algolia/instantsearch.js/issues/1687

Need

Being compatible

Proposal

TBD. Needs a POC.

❄️❄️❄️ hard ♨ API

Most helpful comment

Since there is the resultsState prop on InstantSearch, it could work with any SSR approach. Really like the API!

All 10 comments

Context of the experimentation: usage with Next.js. The goal was to get from the server a page containing all the results.

Difficulties: In order to get all the results at the first render, we need to be able to compute those results before it and inject it. The difficulty came from the fact that the search parameters are computed by each mounted widgets after the first rendering, same for the first search.

Proposal: (names are temp and I'm welcome to discuss them :))

  1. The idea is to create a new InstantSearch inside a server.js file. This InstantSearch will be able to gather all the searchParameters during the componentWillMount phase of every widgets.

  2. By leveraging the getInitialProps function that comes with next.js we can propose a findResults function.
    The goal here is to encapsulate the search call and return a promise.

  3. Finally because using the getInitialProps function only return plain JS object, we need to provide a decorateResults function to rehydrate the results and finally inject it to the <InstantSearch/> instance. (Next.js only I think).

Here's the example using next.js:

  • pages.js
import { Head, IS } from '../components';
import React from 'react';
import { findResults, decorateResults } from 'react-instantsearch/server';

export default class extends React.Component {
  static async getInitialProps() {
    const results = await findResults(IS);
    return { results };
  }

  render() {
    return (
      <div>
        <Head title="Home" />
        <div>
          <IS resultsState={decorateResults(this.props.results)} />
        </div>
        <style jsx>{`

    `}</style>
      </div>
    );
  }
}
  • IS
import React from 'react';
import { RefinementList, SearchBox, Hits } from 'react-instantsearch/dom';
import { InstantSearch } from 'react-instantsearch/server';
export default class extends React.Component {
  render() {
    return (
      <InstantSearch
        appId="latency"
        apiKey="6be0576ff61c053d5f9a3225e2a90f76"
        indexName="ikea"
        resultsState={this.props.resultsState}
      >
        <SearchBox defaultRefinement="chair" />
        <Hits />
        <RefinementList attributeName="category" />
      </InstantSearch>
    );
  }
}

It's not that much of code. I'd say the only pain point is that we need to reimplement the gathering of search parameters depending on the index (to be compatible with MultiIndex).

What do you think?

When using https://zeit.co/blog/next you can't use React InstantSearch.

Could this work:
Not rendering on the server, using a HOC (what we currently do, although we dont use Next).

I also dont understand why you propose solving react-instantsearch SSR just for Next.js and not generally for SSR. Although Next.js is gaining popularity I dont see it being used by serious companies

It’s an example @davidfurlong, once you can get the DOM rendered for first paint with one SSR solution, it can be used in more situations

@davidfurlong: I just replace this phrase with this "you can use React InstantSearch but won't benefit of a good SEO (having all the results since the first rendering).". Is your comment still applying?

About next.js, it was the context of the POC. I'm pretty sure this API can work with other SSR technique.

Its not just a question of SEO but also performance. First render on server is much quicker than rendering on the client after the bundle has been downloaded - our react-instantsearch part is rendered empty for approx 2s until its rendered on the client. On our website this means that theres a white space where the react-instantsearch is not yet rendered, with the rest of the page rendered immediately

Since there is the resultsState prop on InstantSearch, it could work with any SSR approach. Really like the API!

Next steps:

  • [ ] : POC featuring URL Sync
  • [ ] : Implementation
  • [ ] : Guide
  • [ ] : Beta release

Is it much easier to server render without using/with fixed searchParameters? I'd be willing to attempt it if you expect it to be as this solves the problem for us in most use cases

Was this page helpful?
0 / 5 - 0 ratings