Home

Awesome

React on Rails Demo With SSR, HMR fast refresh, and TypeScript

Each commit demonstrates a step in the React on Rails Tutorial.

UPDATE July 2, 2024: This repo is updated to the latest shakapacker gem and package v8.0.0 and React on Rails v14.0.3 releases!


Please ⭐️ this repo if you find this useful.

See the commit history.

Key features

  1. shakpacker v8! (see explanation of the switch at rails/webpacker).
  2. Server-Side Rendering (SSR) of React using a separate server bundle.
  3. Webpack configuration for the server bundle is based on the rails/webpacker configuration for the client files.
  4. HMR is provided by react-refresh-webpack-plugin.
  5. TypeScript
  6. CSS Modules

Installation

Setup

git clone git@github.com:shakacode/react_on_rails_demo_ssr_hmr.git
bundle install
yarn install

Use the provided Procfiles to run webpack and rails together, like overmind start -f Procfile.dev

  1. Procfile.dev: Uses the webpack-dev-server. This will proxy asset requests to the webpack-dev-server except for a few files: the manifest.json and the server-bundle.js which are in the standard public/webpack/development folder.
  2. Procfile.dev-static: Uses the standard files in the public/webpack/development folder. Note, the standard webpack config in /config/webpack outputs an array which builds both the client and server bundles.

Running with HMR

bin/dev
# or
overmind start -f Procfile.dev

Running without HMR, statically creating the bundles

bin/dev-static
# or
overmind start -f Procfile.dev-static

Running with SWC

Starting from Shakapacker 6.1.1, it is possible to use SWC in projects. See demo-branch-swc-loader branch for a demonstration of SWC usage.

Please check out Shakapacker - Using SWC Loader documentation for more information about this feature.

Testing Functionality of SSR and HMR

  1. Start app using either bin/dev or bin/dev-static (or run Procfile.dev or Procfile.dev-static with your favorit process manager like overmind or foreman).
  2. Visit page http://localhost:3000/hello_world.
    1. Inspect the page for no errors and view the console. With HMR (non-static), you'll see a browser console message:[webpack-dev-server] Hot Module Replacement enabled.
    2. Type into the input box and notice the label above change.
  3. Edit React file app/javascript/bundles/HelloWorld/components/HelloWorld.tsx, like changing some text in the React code, and save the file.
    1. With HMR enabled, you'll see a message on the browser console and the page will update automatically.
    2. With static compilation, you'll need to refresh the page to see the update.
  4. Edit the CSS module file app/javascript/bundles/HelloWorld/components/HelloWorld.module.css and change the color. You will either see an instant update to the webpage with HMR, or you will need to refresh the page.
    1. With HMR enabled, you'll see a message on the browser console and the page will update automatically. You'll see browser console messages:
      [webpack-dev-server] App updated. Recompiling...
      index.js:519 [webpack-dev-server] App hot update...
      log.js:24 [HMR] Checking for updates on the server...
      log.js:24 [HMR] Updated modules:
      log.js:16 [HMR]  - ./app/javascript/bundles/HelloWorld/components/HelloWorld.module.css
      log.js:24 [HMR] App is up to date.
      

Checking the production build

  1. RAILS_ENV=production rake assets:precompile
  2. rails s -e production

Debugging the webpack setup

  1. Uncomment the debugger line at the end of file config/webpack/webpack.config.js
  2. Set your preferred environment values and run NODE_ENV=production RAILS_ENV=production bin/webpacker --debug-webpacker

Descriptive Commits

Note, this repo started with rails/webpacker v5 and an older version of React on Rails. These are for example purposes only. They are not a set of tutorial steps if you want to be on the current versions.

  1. Rails new: rails new --skip-sprockets -J --skip-turbolinks test-react-on-rails-v12-ssr-v2

  2. Add webpacker gem: bundle add webpacker

  3. Add React on Rails gem: bundle add react_on_rails.

  4. Set React on Rails version to be exact: Edit the Gemfile and run bundle.

  5. Install webpacker: bundle exec rails webpacker:install

  6. Install webpacker React: bundle exec rails webpacker:install:react

  7. Install React on Rails: rails generate react_on_rails:install

  8. Add HMR and Fast Refresh Leverages the react-refresh-webpack-plugin to have Fast Refresh working with Webpack v4. Note, ensure HMR is enabled for the dev server: hmr: true in webpacker.yml. After this change, you can:

    1. Run: foreman start -f Procfile.dev-hmr
    2. Edit a JSX file and save and see the React change and the component state was preserved.
  9. rails/webpacker installs TypeScript into webpack: bundle exec rails webpacker:install:typescript

  10. Convert demo screen and ReactOnRails registration to Typescript

  11. Enable simple Server-Side Rendering (SSR) for Hello World using the same bundle for client and server rendering. This is the simple, but imperfect way to turn on SSR using the same bundle for the server and client. HMR is not available.

  12. Switch to separate bundle for server-side rendering Convert to separate bundles for server vs. client rendering with HMR

    1. Turned back on hmr and inline in webpacker.yml to support HMR.
    2. Change config/initializers/react_on_rails.rb to have the correct server bundle name
    3. Follow the flow from config/webpack/development.js to webpackConfig.js and consider uncommenting the debug line to see what happens when you run bin/webpacker --debug
  13. Upgrade to rails/webpacker v6

Client only rendering versus Server-Side Rendering

Client Only Rendering

2020-08-02_17-14-33

Server-Side Rendering

2020-08-02_17-10-16

About

This project is sponsored by the software consulting firm ShakaCode. We focus on React front-ends, often with Ruby on Rails or Gatsby, using TypeScript or ReasonML. The best way to see what we do is to see the details of our recent work.

Interested in optimizing your webpack setup for React on Rails including code splitting with react-router, and loadable-components with server-side rendering? We just did this for Popmenu, lowering Heroku costs 20-25% while getting a 73% decrease in average response times.

Feel free to contact Justin Gordon, justin@shakacode.com, maintainer of React on Rails, for more information.

Click to join React + Rails Slack.

ShakaCode is hiring! Check out our open positions.