Skip to content
This repository has been archived by the owner on Aug 2, 2023. It is now read-only.

bellroy/rails-dynamic-rendering

Repository files navigation

N.B. The Bellroy technology team are transitioning away from Ruby as their primary programming language, and will not longer actively update this repository. Contact us if you'd like to take over as the primary maintainer.

dynamic-rendering-logo

Dynamic Rendering Gem Version CI Badge

Is your SEO performance being held hostage by frontend JavaScript UI frameworks? Dynamic rendering is a "workaround solution" (in the words of Google) to help make difficult to index JavaScript based content easier for search engine crawlers to understand by presenting them with a pre-rendered HTML snapshot of your page.

This gem implements dynamic rendering for Rails applications using Puppeteer via the Grover gem.

You can find out more about dynamic rendering in Google's article: https://developers.google.com/search/docs/guides/dynamic-rendering

Is this server-side rendering / SSR?

Kind of - Server-side rendering typically involves pre-rendering JavaScript elements of the page on the server within some isolated NodeJS environment and then having the client "re-hydrate" the DOM after loading. Dynamic rendering differs in that it's targeted specifically at crawler user agents and doesn't involve any "re-hydration" of the DOM, rather it's a static representation of the DOM, a snapshot of how the page looked in a headless Chrome instance.

How does this work?

diagram

Install

gem 'rails-dynamic-rendering'

Usage

Include the concern and then use enable_dynamic_rendering. Any controller action covered by the enable_dynamic_rendering call (which accepts all the same arguments as after_action) will based on the user agent choose to either just return the HTML with JS or choose to render the page in a headless Chrome instance & render back the serialized HTML with all JS removed.

class ApplicationController
  include DynamicRendering::ActsAsDynamicallyRenderable

  enable_dynamic_rendering only: :index, if: -> { some_condition_is_met? }

  def index
    @my_code = 'Does fancy stuff'
  end

  private

  def some_condition_is_met?
    true
  end
end

You can override the built in decision making thats used to determine whether a snapshot of the page should be returned by defining your own #request_suitable_for_dynamic_rendering? method. You might want to do this if you'd like to target other user agents:

def request_suitable_for_dynamic_rendering?
  request.user_agent.include? 'My Problematic Bot That Does Not Render JS Content'
end