Code Monkey home page Code Monkey logo

phase-4-deploying-demo-app's Introduction

Rails and React Heroku Demo App

This app uses a Rails API and React frontend that can be deployed to a single domain. For ease of deployment, both projects are contained in the same repository. All React code is in the /client directory during development.

When the application is deployed, the production version of the React application will be generated on the server and placed in the public directory of the Rails application, where we can use Rails to serve it.

Setup

To run the app locally, install the Rails and React dependencies and set up the database:

bundle install
rails db:create db:migrate db:seed
npm install --prefix client

Install Heroku CLI (if you don't already have it):

brew tap heroku/brew && brew install heroku

Running the App in Development

Configuration for running in development is in the Procfile.dev file. Run this command to start the frontend and backend servers:

heroku local -f Procfile.dev

In development, requests from the React app are proxied, so you can write something like this (without using a domain):

fetch("/me").then((r) => r.json());

Since our deployed app will run on the same domain, this is a good way to simulate a similar environment in development.

Deploying

Login to Heroku:

heroku login

Create new Heroku app:

heroku create

Add buildpacks for Heroku to run:

  • Rails app on Ruby
  • React app on Node
heroku buildpacks:add heroku/nodejs --index 1
heroku buildpacks:add heroku/ruby --index 2

Deploy:

git push heroku main

Code Explanations

There are a few areas of the code that differ from the typical Rails API setup that merit explanation.

Cookies/Sessions Setup

By default, when generating a new Rails app in API mode, the middleware for cookies and sessions isn't included. We can add it back in (and specify the SameSite policy for our cookies for protection):

# config/application.rb

# Adding back cookies and session middleware
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore

# Use SameSite=Strict for all cookies to help protect against CSRF
config.action_dispatch.cookies_same_site_protection = :strict

We also need to include helpers for sessions/cookies in our controllers:

# app/controllers/application_controller.rb

class ApplicationController < ActionController::API
  include ActionController::Cookies
end

Now, we can set a session cookie for users when they log in:

def create
  user = User.find_by(username: params[:username]).authenticate(params[:password])
  session[:user_id] = user.id
  render json: user
end

Deploying Setup Explained

We'll deploy our frontend and backend to Heroku on one single app. There are a couple key pieces to this configuration. First, the Procfile:

web: bundle exec rails s
release: bin/rake db:migrate

This gives Heroku instructions on commands to run on release (run our migrations), and web (run rails server).

Second, the package.json file in the root directory (not the one in the client directory):

{
  "name": "phase-4-deploying-app-demo",
  "description": "Build scripts for Heroku",
  "engines": {
    "node": "16.x"
  },
  "scripts": {
    "build": "npm install --prefix client && npm run build --prefix client",
    "clean": "rm -rf public",
    "deploy": "cp -a client/build/. public/",
    "heroku-postbuild": "npm run clean && npm run build && npm run deploy"
  }
}

The heroku-postbuild script will run when our app has been deployed. This will build the production version of our React app. It does the following:

  • removes any old versions of the React code by deleting the public directory
  • installs the frontend dependencies with npm install
  • builds a production version of the React application with npm build in the client/build directory
  • copies the built version of the React code into the public directory

When a request comes to our server, we can decide if it's request for an API resource, or a request to view the React application. If it's an API request, we can send back JSON data from the controller. Otherwise, we can send back the index.html file from our public directory and run the React application.

React Router

For our deployed app, we need non-API requests to pass through to our React application. Otherwise, routes that would normally be handled by React Router will be handled by Rails instead.

Setup routes fallback (make sure this is the last route defined in the routes.rb file):

# config/routes.rb
get '*path', to: "fallback#index", constraints: ->(req) { !req.xhr? && req.format.html? }

Add controller action:

class FallbackController < ActionController::Base

  def index
    render file: 'public/index.html'
  end
end

Note: this controller must inherit from ActionController::Base instead of ApplicationController, since ApplicationController inherits from ActionController::API. API controllers can't render HTML. Plus, we don't need any of the auth logic in this controller.

phase-4-deploying-demo-app's People

Contributors

ihollander avatar lizbur10 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.