I enjoy building back-end in Rails because of its simplicity and convention over configuration principle. I like React on the front end because of its modularity derived from the use of components. I prefer webpack as build tool as I have less problems with it compared to Rails' sprocket.
There are existing gems such as react-rails and react-on-rails that help in building a React app with a Rails backend but I wanted to build a stack without any additional gems.
My approach is as follows:
- Have a react directory
/app/assets/react/
which contains all React components. With Redux or Flux, the relevant Actions, Stores, Dispatchers, etc go into this directory too. - Use webpack with babel to bundle the React application into a
/app/assets/javascripts/bundle.js
- Require
bundle.js
in Rails' defaultapplication.js
- Somewhere in rails view, place the react element.
The code snippets can be found in the Gist at the end of this post.
Now let’s go through it step by step.
Since I’m writing React in ES2015, I’ll be using Babel to transpile the javascript. So I’ll need a .babelrc
with the necessary presets:
{
"presets": ["es2015", "react"]
}
The dependencies need to be added into package.json
.
{
"dependencies": {
"babel-core": "^6.10.4",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.11.1",
"events": "^1.1.1",
"flux": "^2.1.1",
"react": "^15.2.1",
"react-dom": "^15.2.1",
"react-router": "^2.6.0",
"webpack": "^1.13.1"
}
}
babel-core
, babel-loader
, and webpack
are needed for bundling with webpack. babel-preset-es2015
and babel-preset-react
are needed for transpiling react and es2015. In the sample project, I used flux, hence events
and flux
are needed. The rest are required React packages.
I’m not going through the steps to create a React application in detail, so let’s assume there is an existing React project. This should go into the directory /app/assets/react
. Likewise I’m assuming there is an existing Rails application so I’m not going into that.
Now we have all the React code in /app/assets/react
and the Rails code in its usual place. We need to tell webpack how to bundle the React code using webpack.config.js
.
module.exports = {
entry: "./app/assets/react/main.jsx",
output: {
path: __dirname + "/app/assets/javascripts",
filename: "bundle.js"
},
resolve: {
extensions: ['', '.js', '.jsx']
},
module: {
loaders: [
{ test: /\.jsx$/, loader: 'babel-loader' }
]
}
}
This tells webpack to start from ./app/assets/react/main.jsx
. Using Babel, it will transpile all React and ES2015 code in files with .js
and .jsx
extensions into a single bundle.js
located in /app/assets/javascripts
.
Now the React application is ready to be served as static asset. We need to include bundle.js
into the page served by Rails. To do that, add //= require_tree .
at the end of application.js
. This will include bundle.js
which is located in the same directory as application.js
.
In my example, I placed <div id="React"></div>
in home view /app/views/home/index.html.erb
. This is the element where React will render its components.
To see it in action, run webpack
then rails server
.