fbpx Skip to content

Aquent | DEV6

Prerendering Web Apps

Written by: Khalil Stemmler

Intro

SEO is an important component of many applications and websites. When marketing teams and developers come together, SEO, done correctly, can help to create a good source of organic traffic and improve the sharability of your web app. Yet for something so important, it’s often easy to overlook the considerations (and limitations) when it comes to application architecture design.

This article will explain some common scenarios and their SEO pitfalls, what prerendering is, and how it can help you create dynamic SEO-enabled content in your web apps. 

What is Prerendering?

Prerendering web apps is the process of loading a webpage ahead of time, waiting for it to finish rendering, and then returning the resulting HTML and JavaScript as the result to the requesting entity.

Prerendering is one of the possible solutions to creating rich dynamic content that search engines can crawl.

The truth is, search engines are able to execute JavaScript, but when our web page relies on some data from an asynchronous network call in order to describe the content of the page, that’s where we run into problems. Prerendering is one of two ways to solve this issue (the other being server-side rendering).

Common Scenarios

Let’s say that you’re working on a social network application where each user can update their profile and create dynamic content like posts or events.

If Bill, a user of your social networking app, shares their profile located at https://petlovers.com/billybobthorton to their Facebook timeline, depending on how you’ve architected your application, the Preview Link might not look as you intended. 

Common Scenarios

Using the React Helmet in a React application, the code to render a User Profile page might look like something as follows:

import React from 'react'  
import Helmet from 'react-helmet';  
import request from 'request';  

const MetaTags = ({ title, description, image }) => {  
  return(  
    <Helmet>  
      {/* General tags */}  
     <meta name="title"content={title} />  
      <meta name="description"content={description} />  
      <meta name="image"content={image} />  

      {/* OpenGraph tags */}  
      <meta property="og:title"content={title} />  
      <meta property="og:description"content={description} />  
      <meta property="og:image"content={image} />  
    </Helmet>  
  )  
}  
 
export default class UserProfile extends React.Component {  
    constructor(props) {  
    super(props);  
    this.state = { profile: null}  
  }  
 
  getProfile = (userHandle) => { 

return request(`https://api.petlovers.com/profile/${userHandle}`)  
  }  
 
    componentWillMount = async () => {  
    const{ match: { params } } = this.props;  
    try{  
      const profile = await this.getProfile(params.user);  
      this.setState({  
        profile 
      }) 
    } catch(err) {  
      alert("Couldn't load profile");  
    }  
  }  
       
  render () { 
    const{ profile } = this.state;  
    if(!profile) return<div>Loading...</div>;  
 
    return(  
      <div>  
        <MetaTags  
          title={`Petlovers | @${profile.name} - ${profile.featuredPetType} owner`}  
         description={`${profile.tagline}`} 
          image={`${profile.photoUrl}`}  
        /> 
        ... 
        ... 
      </div>  
    )  
  }  
} 

In this code sample, we’re requesting the user’s profile information by sending an API request to https://api.petlovers.com/profile/${userHandle} in componentWillMount (). 

After the request has completed, we save the details to local state, which allows us to set the meta tags for the page.

The problem is that we cannot force search engines to wait for our asynchronous requests to finish before using the computed HTML as the result for what to index.

Even intelligent search engines like Google won’t be able to capture our unique title, description and image for this url.

api request

How prerendering solves this problem

Prerendering services allow you to install some middleware on your server (Apache, Node.js, Nginx, etc) or configure it in your cloud setup (S3 is another valid use case for serving files statically) that checks each request to see if it’s from a web crawler. 

If the request is from a crawler, the middleware will send a request to obtain the static HTML for that page from a prerendering service. The prerendering service is configured to run your page in a headless browser and specifically wait for all network requests to complete before responding with the static HTML. 

For requests coming from actual users, it will continue to serve those requests normally. It’s important to keep the latency low for actual users, but we don’t care about how long it takes for web crawlersas long as they get the correct data.

Prerendering middleware can detect whether the requesting entity is a user or a crawler by doing some regex magic on the user-agent in the headers of the request.

prerendering web apps process

When to consider prerendering

When your application architecture has already been put together and a considerable amount of work has been done, if you need to make SEO improvements, it’s a good idea to use a prerendering service.

For new projects, there are frameworks such as Nuxt.js for Vue and Next.js for React that allow you to do server-side rendering. 

Consider prerendering when you’re adding SEO and dynamic content to your application and it’s not feasible given your current architecture to start server-side rendering certain routes in your app.

  • For example, if you’re serving your web app statically on AWS S3, you’re not going to be able to do server-side rendering easily.
  • But if you were serving your website from Express.js behind a reverse proxy, you might be able to hook up server-side rendering for particular routes.

Other considerations

Caching

Depending on your strategy, you may realize that you need to refresh the cache occasionally for certain routes. Let’s say if a user updated their profile, you’d want that to be refreshed. Services like Prerender.io expose an API so that you can recache a specific route programmatically from your backend.

Conclusion

In this article about prerendering, we explained what prerendering is and how it can assist you in creating dynamic content for the web. We also covered the fundamentals of how it works and when you should consider using prerendering instead of server-side rendering.