We will use Rails to initialize the project demo-rails-with-react-frontend:
# Create a new rails project
$ rails new demo-rails-with-react-frontend -j esbuild
$ cd demo-rails-with-react-frontend
# Make some folders and files for our React application
$ mkdir app/javascript/components
$ touch app/javascript/components/application.tsx
# Add in our React dependencies
$ yarn add react react-dom
# Create a basic components controller
$ bin/rails g controller components index
# Start the server - we use `bin/dev` instead of `bin/rails s`
$ bin/dev
The above does the following:
Create a new Rails project in demo-rails-with-react-frontend with the -j esbuild flag to setup JavaScript with ESBuild.
Add in our React dependencies.
Create a basic components controller that we will set as our root route.
Start the server with bin/dev.
The -j flag for Rails helps us define which JavaScript setup we want. As denoted by the bin/rails new --help command:
At this stage, our project should be ready on localhost:3000, but there are a few other changes that we need to make first.
Setting up our React Application
The first thing we want to do is setup our application to use React.
ESBuild will support TypeScript out of the box, so the first thing we want to do is update our file `app/javascript/application.js to app/javascript/application.ts.
Note: given that app/javascript/application.ts is only for housing our imports, it will not be that necessary but we will do so anyway.
Inside of app/javascript/application.ts, update the file to the following:
// Entry point for the build script in your package.json
import "@hotwired/turbo-rails";
import "./components/application";
We will leave the @hotwired/turbo-rails import as we found it, but then we will add a reference to components/application where our contrived React application code will go.
Finally, we want to update the code within app/javascript/components/application.tsx to the following:
import * as React from "react";
import * as ReactDOM from "react-dom";
interface AppProps {
arg: string;
}
const App = ({ arg }: AppProps) => {
return <div>{`Hello, ${arg}!`}</div>;
};
document.addEventListener("DOMContentLoaded", () => {
const rootEl = document.getElementById("root");
ReactDOM.render(<App arg="Rails 7 with ESBuild" />, rootEl);
});
The above code simply defines a React component that will be rendered to the DOM and has a TypeScript interface to prove TypeScript syntax is valid and working.
While the code is contrived (and not necessarily well organized with the whole components/application.tsx convention), it is a good example of how we can use ESBuild to support TypeScript and how we can set up our React component.
The last things that we need to do is update our view to provide the root div element with ID root and to update our routes.rb file to set our components#index method as our default.
Updating our view and routes
During our rails g controller components index code that we ran at the beginning, we also generated the view app/views/components/index.html.erb.
Within that file, we need to add our div for our React app to hook into. Update the code in that file to the following:
<h1>Components#index</h1>
<div id="root"></div>
Finally, within config/routes.rb, update the file to set components as the index default:
Rails.application.routes.draw do
root 'components#index'
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Defines the root path route ("/")
# root "articles#index"
end
Finally, we can head to localhost:3000 and see our React application.
React app
Summary
Today's post demonstrated how we can set up a Rails 7 project using ESBuild to support our React + TypeScript applications.
Rails 7 comes with a few neat options for how we can set up our project, and ESBuild is one of those options that comes out-of-the-box.