Introduction and setup of Webpack with react_on_rails gem

Linked Projects:

Calreact

‚ú® 1 person thanked Hrishi Mittal for this tutorial.

ūüĎć Send Thanks
 

Lesson code - https://github.com/learnetto/calreact/tree/calreact-ror

In this module we're going to look at using React with Webpack inside Rails using the react_on_rails gem.

Why use the react_on_rails gem?

The key difference with react-rails is that it uses EcmaScript 6 (ES6) by default and state-of-the-art JavaScript tooling, including Webpack, instead of relying completely on the Rails asset pipepline. 

Although the latest version of react-rails has also introduced support for Webpack (via the webpacker gem), react_on_rails was originally created with the explicit aim of supporting native JavaScript tools including Webpack.

react_on_rails also  doesn't depend on jQuery.

react_on_rails uses Webpack for ES6 compilation and then uses the Rails asset pipeline to simply include the bundled asset file that Webpack generates.

You can use npm to install JavaScript libraries, instead of having to use gems or manually downloading and including them in our application manifest files, like we did in the previous lessons with react-rails.

So it gives you a lot more power at the cost of installing and managing a few extra things.

And most of this power comes from using Webpack.

What is Webpack?

Webpack is a module bundler. 

Webpack

It's a tool for processing and bundling your assets in convenient chunks and serving them efficiently to the client.

It'll automatically find all the required dependencies, convert our JSX and ES6 code to ES5 and concatenate  all our assets into bundles, making sure all the code is loaded in the correct order.

It has many powerful features including plugins, loaders and code splitting which allow you to do practically everything you need to do with your assets - not just javascript but CSS, fonts and images too.

But because it's so powerful, it can be confusing when you're starting out. You can get lost trying to learn everything about Webpack.

We don't want to do that. So for the purpose of this lesson, we're simply going to see how the react_on_rails gem sets up Webpack for us. We can look at it in more detail later on.

The first thing we need to do in order to use the react_on_rails gem is to install Node.js. 

We're not going to use node as a server for now, just for installing javascript packages using npm - the Node Package Manager. It's like Ruby Bundler for Javascript.

You can download a Node installer from the official website nodejs.org.

You can also install it using brew on a Mac or through Node Version Manager (nvm), which is like rvm for Ruby.

Once you've installed node, you can check that it's installed correctly by running the following command in the terminal:

node -v

That'll show you the version of node on your machine.

Ok, so let's get started with a react_on_rails app.

I'm going to create a new app, let's call it calreact again to show you the default setup of the react_on_rails gem.

$ rails new calreact

Then let's add the react_on_rails gem to its Gemfile.

gem 'react_on_rails', '~> 6'

Important Note about react_on_rails gem version:

At the time of recording this lesson, the latest react_on_rails gem version was 6.4.2, which did not depend on the yarn package manager, and only used npm.

However, the latest version of the gem requires yarn. So you can either specify the exact version in your Gemfile like this:

gem 'react_on_rails', '6.4.2'

Or if you want to use the latest gem with yarn, you can install yarn first and then replace all npm install commands in the lesson with yarn. On Mac OS X, you can install yarn with brew:

brew install yarn

After adding the gem to the Gemfile, run bundle:

$ bundle

Next we need to run the gem's generator. 

But before we can do that, the gem requires us to commit all our changes to git. So let's do that quickly by initialising a new repo, adding all changes and committing them.

$ git init
$ git add -A
$ git commit -m "New Rails 5 app with react_on_rails"

Now we can run the generator:

rails generate react_on_rails:install

This generator will create a bunch of files and directories and add some configuration to our app.

Files and config generated by react_on_rails
The big change it makes is it adds a client directory in our app's root directory.

That is where all our client side code is going to live. This is a big difference with the react-rails gem, which just uses the default Rails structure and puts our React components under the app/assets/javascripts directory. react_on_rails puts everything under this separate client directory.

It also creates an example React component called HelloWorld which we can test right away to check if React's working in our app.

Then it tells us what to do next. Run bundle && npm install. npm install is like bundle install.

So let's run that:

bundle && npm install

If you're running a more recent version of react_on_rails, you need to run yarn instead:

bundle && yarn

Now that we've installed all the gems and node packages, we can run the app using foreman.

Foreman is a gem for running apps when you have more than one process to run at once. We tell foreman what processes to run in a Procfile.

In our case, we need to run rails as well as webpack. The react_on_rails gem generated a file called Procfile.dev.

First, let's install foreman:

$ gem install foreman

Now let's run it with Procfile.dev:

$ foreman start -f Procfile.dev

Now if we open up a browser and go to http://localhost:3000/hello_world, we'll see the example React component HelloWorld that comes with the react_on_rails gem.

Example React component from react_on_rails


When you type in the input text field, it updates the state and shows the same field value above it.

Ok, so now that we've seen how to set up this gem, let's take a step back and go through all the steps that we took and see how it really works in detail.


We first ran the generator which created the client directory and files inside it, and some manifest files and a Procfile.

Then we installed the dependent gems and node packages. So let's look at how that works. 

When we run npm install (or yarn), it first looks in the package.json file in our root directory:

package.json

This is like a Gemfile with some extra features, but this file doesn't do a lot. It mainly just has a postinstall script which does the bulk of the setup.

That says cd into the client directory and run npm install there.

The gem's generator also created a manifest file called package.json inside the client directory.

client/package.json

It lists a bunch of libraries our app needs as dependencies in production or development. These are ones you'd want both in production and development. and devDependencies are only for development. When we run npm install, all these packages get installed.

And they all go into a directory called node_modules. There's a lot of stuff in there but don't worry, we're not going to edit any of that.

The client/package.json file also has some scripts it can run, which we'll look at in a moment.

Our next step was to start the app by running foreman with Procfile.dev. 

Procfile.dev
It has 2 processes. The web process will run rails on port 3000. And the client process will do a couple of things.

First it deletes all files under this app/assets/webpack directory because every time we restart our server, webpack recreates those files. Then it goes into the client directory and runs this script - 

npm run build:development

And that's one of the scripts defined in package.json that we just saw.
    "build:development": "webpack -w --config webpack.config.js"

It's going to run webpack with the config file webpack.config.js which is where we define all the settings for webpack to process and bundle our assets.

The main thing in this file is the config object, which has several parts:

entry is the entry point, where webpack starts reading all dependencies. you can have multiple entry points but the important one for us here is this file which it will use as a starting point for setting up the example HelloWorld component.

output defines where webpack is going to save the bundled output - in this case, app/assets/webpack in the root directory.

resolve tells webpack which filetypes we want to include, so we can require files without their extension - say require('file') instead of require('file.js').

plugins are used for customising the build process. we don't need that right now.

Then we have a couple of loaders, which preprocess files.
We have one which adds some legacy ES5 functionality and the babel-loader which is going to convert our JSX into ES5.

test defines the pattern to match files for the loader to run on and loader is the name of the loader.

We can also exclude directories.

So that's briefly the default webpack setup that react_on_rails creates for us.

Based on this config, webpack creates a webpack-bundle file in the app assets webpack directory.

But how does that get included in our rails asset pipeline? The react_on_rails gem adds it to the application.js manifest file.

application.js

But notice it doesn't add the full path of the file. That's because it adds the path to the config/initialiser/assets.rb file. So the file can be required directly.

Ok, now let's look at the example React component that the gem created.

We can start by looking at the entry file defined in the webpack config inside the client directory - app/bundles/helloworld/startup/registration.jsx.

client/app/bundles/helloworld/startup/registration.jsx

So here you can see we're using ES6 by default. First we  import ReactOnRails, which is the Javascript API of the gem. Then we import the HelloWorld component and then we register it with the gem's API.

This is how react_on_rails is able to use a component from a Rails view. 

Now let's look at the HelloWorld component.

HelloWorld component

First we need to import React and proptypes from React.

If you remember from the previous lessons, when we use the react-rails gems we didn't need to specifically import React.  We were able to directly use React.createclass to make our components.

Now while that may seem more convenient, we're going to follow this ES6 modules format from now on because it makes us be very specific about what libraries, modules or components we're including in any bit of code we write, so that we only include the code we want.

We're defining our component as a subclass of React.Component, which we're already familiar with from our previous lessons.

In addition we're also exporting this class by default. And that's how we're able to import it by name in registration.jsx.

We have a constructor function that accepts props and _railsContext (which is a convenience helper for getting details about the request like the current path).

The constructor sets the state and then we have a function called updateName for handling state changes.

Finally the render function returns a div which displays a hello message with the name which it gets from the input form field.

Once the component is defined, the last piece of the puzzle is to use it in our Rails view. We do that in exactly the same way we did with the react-rails gem.

So let's look in the app/views/hello_world folder in index.html.erb:

react_component view helper method

We have the react_component view helper method which accepts the name of the component and some props. We can also set prerender to true if we want server side rendering.

So that's all for this lesson.

Next we're going to look at using the react_on_rails gem in our calendar appointments app.

Liked this tutorial? Get more like this in your inbox