Many frontend frameworks rely on JavaScript to show content. This can mean Google might take some time to index your content or update the indexed content. One workaround option is to implement dynamic rendering. Dynamic rendering means switching between client-side rendered and pre-rendered content for specific user agents. This codelab will walk you through implementing dynamic rendering using Rendertron, which is an open source solution based on headless Chromium.

A diagram that shows how dynamic rendering works. The diagram shows the server serving\n              initial HTML and JavaScript content directly to the browser. In contrast, the diagram\n              shows the server serving initial HTML and JavaScript to a renderer, which converts the\n              initial HTML and JavaScript to static HTML. Once the content is converted, the\n              renderer serves static HTML to the crawler.

What you'll learn

What you'll need

Clone the Glitch sample

You'll use a sample web app for this codelab. To create your own, editable copy for this codelab, clone the sample app in Glitch:

Clone the sample app

Set up Google Cloud project

Create a new Google Cloud Platform project. You'll need the Project ID in a later step.

Let's take our web app for a spin in the Mobile-Friendly Test. This will give us an idea how our web app is seen by Google Search. It's important that all content is visible to Google Search in order for our web app to be indexed correctly. If our cats aren't visible in this test, users won't be able to find them via Google Search. Here is the result:

The screenshot shows a blank space where the cat images are supposed to be.

To view a JavaScript error that is preventing the content from showing up correctly, click View details.

In this codelab, you will use dynamic rendering as a way to make the content available for search engines and crawlers that don't run JavaScript, and as a side effect also work around the JavaScript issue. You will use Rendertron to perform the rendering for crawlers and bots.

Rendertron runs a server that takes a URL and returns static HTML for the URL by using headless Chromium. This guide follows the recommendation from the Rendertron project.

  1. To clone the Rendertron repository from GitHub, run the following command:
git clone https://github.com/GoogleChrome/rendertron.git
  1. Change directories:
cd rendertron 
  1. To install dependencies and build Rendertron on your computer, run the following command:
npm install && npm run build
  1. Create a new file called config.json in the rendertron directory with the following content to enable Rendertron's cache:
{ "datastoreCache": true }
  1. From the rendertron directory, run the following command. Replace YOUR_PROJECT_ID with your project ID that you set in Google Cloud Platform.
gcloud app deploy app.yaml --project YOUR_PROJECT_ID
  1. Select a region of your choice and confirm the deployment. Wait for the command to finish.
  2. Enter YOUR_PROJECT_ID.appspot.com in your browser. Replace YOUR_PROJECT_ID with your actual project ID that you set in Google Cloud Platform. You should see Rendertron's interface with an input field and a few buttons.

When you see the Rendertron web interface, you have successfully deployed your own Rendertron instance. Take note of your project's URL (YOUR_PROJECT_ID.appspot.com) as you will need it later.

To add Rendertron to the server, install Rendertron, add Googlebot to the bot list, and configure the Rendertron middleware to sent bot requests.

Install Rendertron

The web server uses express.js and Rendertron has an express.js middleware. To add rendertron-middleware to your copy of the sample app, open the package.json file in your remixed Glitch and add rendertron-middleware to the dependencies like this:

  "dependencies": {
    "express": "^4.16.4",
    "rendertron-middleware": "^0.1.5"
  },

Add the rendertron-middleware to the server.js file in your remixed Glitch.

const rendertron = require('rendertron-middleware');

Configure the bot list

Rendertron uses the user-agent HTTP header to determine if a request comes from a bot or a user's browser. To make Rendertron render Googlebot requests as well, add Googlebot to the list of user agents. Paste the following snippet to the server.js file in your remixed Glitch:

const BOTS = rendertron.botUserAgents.concat('googlebot');
const BOT_UA_PATTERN = new RegExp(BOTS.join('|'), 'i');

You'll use this regular expression in the next step when you configure the Rendertron middleware.

Configure the Rendertron middleware

To send bot requests to the Rendertron instance, add the middleware to the server.js file. The middleware checks the requesting user agent and forwards requests from known bots to the Rendertron instance. Add the following code to the server.js file in your remixed Glitch project before the first line that starts with app.get:

app.use(rendertron.makeMiddleware({
  proxyUrl: 'https://YOUR_PROJECT_ID.appspot.com/render',
  userAgentPattern: BOT_UA_PATTERN
}));

Bots requesting the sample website receive the static HTML from Rendertron, so the bots don't need to run JavaScript to display the content.

To test if the Rendertron setup was successful, run the Mobile-Friendly Test with your glitch.com project URL. You should see "Page is mobile-friendly" and the screenshot should show the full content of the page (for example, no missing images).

The cat pictures are now visible. In the HTML tab, you can see the HTML that the JavaScript code generated and that Rendertron removed the need for JavaScript to display the content.

You created a dynamic rendering setup without making any changes to the web app frontend code. With these changes, you can serve a static HTML version of the web app to crawlers.

What we've covered

Learn more

Keep learning about JavaScript and SEO: