Guides / Building Search UI / Going further

Dynamic rendering with InstantSearch.js

InstantSearch.js does not support server-side rendering (SSR). However, it is possible to get some of the SSR benefits using another technique: dynamic rendering.

Dynamic Rendering

In a nutshell, dynamic rendering allows to switch between client-side rendered and pre-rendered content for specific user agents, namely search engines user agents. This means that whenever your server receives a request, it first looks at the user agent to determine whether it’s coming from a search engine or a regular user.

  • If the request is coming from a search engine, the response is proxied through a headless browser that pre-renders it.
  • If the request is coming from a regular user, the response is rendered client-side.

Build an InstantSearch app

The easiest way to setup a basic InstantSearch app is using create-instantsearch-app. Install create-instantsearch-app and create your app.

$
$
npm install -g create-instantsearch-app@latest
create-instantsearch-app my-app

Feel free to pick any InstantSearch flavor your like. Pick the default values for the rest of the options.

Run the build command and confirm it produced a dist/ folder.

$
$
cd my-app
npm run build

Add a basic Express.js server that will serve our static files.

$
$
npm install --save express
touch index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// index.js
const express = require('express');
const app = express();

app.use(express.static('dist'));

const port = process.env.PORT || 3000;
app.listen(port, err => {
  if (err) {
    console.error('failed to start server.');
    return;
  }
  console.log(`server started at http://localhost:${port}/`);
});

Now run the server and visit http://localhost:3000 to make sure everything is working.

$
node index.js

Set up and configure a dynamic renderer

Google recommends using either rendertron (free, self-hosted) or prerender.io (fully hosted). In this example, we’ll be using rendertron.

$
$
npm install -g rendertron
PORT=3001 rendertron &

Our pre-renderer is now listening on port 3001 and ready to render JavaScript generated content into HTML.

Proxy your requests through Rendertron

You need to send every request with the Content-Type: text/html header and the relevant user agent to the URL of Rendertron: http://localhost:3001/render.

Depending on your stack, there are multiple ways you can achieve this kind of proxying, but if you’re using an Express.js server, rendertron-middleware can handle this proxying for you.

$
npm install --save rendertron-middleware
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const rendertronMiddleware = require('rendertron-middleware');

/* ... */

app.use(
  rendertronMiddleware.makeMiddleware({
    proxyUrl: `http://localhost:3001/render/`, // rendertron address with a /render/ suffix
    timeout: 60 * 1000,
    userAgentPattern: /googlebot|bingbot/i // by default
  })
);

app.use(express.static('dist'));

/* ... */

Feel free to adjust the userAgentPattern or use the default values.

Close and restart your server, then run this curl command to confirm pre-rendering works.

$
curl --user-agent "googlebot" http://localhost:3000/
Did you find this page helpful?