Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Including React (react-rails) into a Rails Engine

EDIT: Answered my own question in detail below, so editing this retro-actively to simplify the question

How do I include ReactJS into my Rails Engine?

If I add the react-rails gem directly, I get the error

React::ServerRendering::PrerenderError in Blorgh::Dashboards#show
Encountered error "#<ExecJS::ProgramError: TypeError: undefined is not an object (evaluating 'this.ReactRailsUJS.serverRender')>" when prerendering SomeComponent
like image 580
user2490003 Avatar asked Feb 17 '26 21:02

user2490003


1 Answers

The lack of documentation and blog posts on this topic is painful. I would have imagined it to be a more popular request.

For anyone else struggling, I was able to do some hair pulling and get the below setup to work!

Disclaimer: I have no idea how "correct" this solution is and whether it's recommended or not. I'd love for someone who knows more about rails engines and the asset pipeline to edit as needed.

I tested this in all 4 combinations of development/production and prerender: true / prerender: false. (I tested production on my local machine by setting RAILS_ENV)

Definitions

The below examples use the following definitions

  • blorgh - Name of your engine (lifted from the official Rails docs)
  • SomeComponent / some_component.jsx - Name of a React component we want to include
  • RAILS_ROOT - The root path of the dummy host application inside your engine test or spec folder
  • ENGINE_ROOT - The root path of your Rails Engine

Setup

As per the react-rails docs, run the generator from your ENGINE_ROOT which will create several files for you.

rails generate react:install

Engine Configuration - Assets Folder

Folder structure should be -

- app/
  - assets/
    - config/
      - blorgh_manifest.js
    - javascripts/
      - blorgh/
        - components/
          - some_component.jsx
        - application.js
        - components.js
        - server_rendering.js

Both components.js and server_rendering.js essentially include React for you and then require your components under the components/ folder. But components.js is included through application.js whereas server_rendering.js is invoked when you are pre-rendering server side

The manifest itself I don't understand very well, but like it's name suggests it seems to be a manifest of all your engine's CSS and JS assets

Manifest (this should already exist, just including for clarity)

# app/assets/config/blorg_manifest.js
//= link_directory ../javascripts/blorgh .js
//= link_directory ../stylesheets/blorgh .css

Application

# app/assets/javascripts/blorgh/application.js
//= require react
//= require react_ujs
//= require ./components
//= require_tree .

Components

# app/assets/javascripts/blorgh/components.js
//= require_tree ./components

Server Rendering

# app/assets/javascripts/blorgh/server_rendering.js
//= require react-server
//= require react_ujs
//= require ./components

Some Component (just a sample to test with)

var SomeComponent = React.createClass({
  propTypes:{
  },

  getInitialState: function() {
    return {};
  },

  render: function() {
    return (
      <div>
        THIS IS IN REACT WOOHOO
      </div>
    );
  }
});

Engine Configuration - Application

Engine Initializer - need to namespace the file for asset prcompilation

# config/initializers/react_server_rendering.rb
Rails.application.config.assets.precompile += ["blorgh/server_rendering.js"]

Engine - require react and configure it

require "react-rails"

module Blorgh
  class Engine < ::Rails::Engine
    isolate_namespace Blorgh

    # ....
    initializer("blorgh.react-rails") do |app|
      app.config.react.variant = Rails.env.to_s

      # Make sure the file is explicitly referenced for server side rendering
      app.config.react.server_renderer_options = {
        files: ["blorgh/server_rendering.js"]
      }
    end
  end
end

HTML View - render the component

<%= react_component("SomeComponent", {}, { prerender: false }) %>
# or
<%= react_component("SomeComponent", {}, { prerender: true }) %>

Host application configuration

Your host application should include your engine's assets. To do that, you need to instruct the users of your engines to add this to their application files

#{RAILS_ROOT}/app/assets/javascripts/application.js
// Make sure it appears above `require_tree .`
//= require blorgh_manifest.js

Run it in development

Now when you run rails server the above should load your component

Testing "Production" locally

If you want to ensure everything runs ok on production, you'll want to run your app in production mode locally

cd RAILS_ROOT
rake assets:precompile
cd ENGINE_ROOT
RAILS_SERVE_STATIC_FILES=true SECRET_KEY_BASE=(...) rails s -e production
like image 175
user2490003 Avatar answered Feb 19 '26 10:02

user2490003



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!