From c1089f0e1d3fba56424a3c9ed0d4b71373d26e76 Mon Sep 17 00:00:00 2001 From: hoshinotsuyoshi Date: Sat, 19 Oct 2024 21:22:21 +0900 Subject: [PATCH] Add README --- README.md | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..7fe2a69 --- /dev/null +++ b/README.md @@ -0,0 +1,166 @@ +# Monorepo for Rails GraphQL API and Vite + React SPA + +This monorepo hosts two main applications: +- A **Rails GraphQL API** running in API mode located in `./backend` +- A **Vite + React Single Page Application (SPA)** located in `./frontend` + +## Project Structure + +```bash +$ tree -L 2 +. +├── backend # Rails GraphQL API (API mode) +│   ├── Dockerfile # Dockerfile for the Rails backend +│   ├── Gemfile # Gem dependencies +│   ├── Gemfile.lock +│   ├── README.md +│   ├── app # Rails application code +│   ├── config # Rails configuration +│   ├── public # Contains compiled frontend assets +│   ├── spec # RSpec tests +│   └── ... +├── frontend # Vite + React SPA +│   ├── README.md +│   ├── package.json # Frontend dependencies and scripts +│   ├── src # React source code +│   ├── dist # Build output for the frontend app +│   └── ... +└── graphql-schema # GraphQL schema files + └── backend_schema.graphql +``` + +## Deployment Process + +The deployment process involves building the frontend, syncing the build artifacts to the Rails `public/` directory using `rsync`, and building the Docker image for the Rails API. + +### Steps: + +1. **Build the frontend** + Navigate to the `frontend` directory and run the build command using Bun. This compiles the React app and outputs the assets to `frontend/dist/`: + ```bash + cd frontend && bun run build + ``` + +2. **Move frontend build artifacts to Rails** + After the frontend build is complete, the compiled assets are moved into the Rails public directory using `rsync` for efficient file synchronization: + ```bash + rsync -av --delete dist/index.html ../backend/public/ + rsync -av --delete dist/assets/ ../backend/public/assets/ + touch ../backend/public/assets/.keep + ``` + + This ensures that the frontend's `index.html` and `assets/` files are correctly placed in the `backend/public/` directory. The `.keep` file ensures that the `assets/` directory is maintained even if it is empty. + +3. **Build the Docker image** + After the assets are moved, the Rails backend can be built into a Docker image: + ```bash + cd backend && docker build -t my-spa . + ``` + +### Example Script + +Here’s a simple shell script that combines the above steps: + +```bash +#!/bin/bash + +# 1. Build the frontend +cd frontend && bun run build + +# 2. Move build artifacts to Rails public directory +rsync -av --delete dist/index.html ../backend/public/ +rsync -av --delete dist/assets/ ../backend/public/assets/ +touch ../backend/public/assets/.keep + +# 3. Build the Docker image for Rails API +cd ../backend && docker build -t my-spa . +``` + +## Rails Setup (API Mode) + +The Rails application serves the frontend SPA's assets for specific routes listed in `config/routes.rb`. These routes point to a static controller, which renders the `index.html` file served by the frontend. + +```ruby +# config/routes.rb +to = "static#index" +[ + "/login", + "/me", + "/onboarding/verify_email_address", + "/set_password", + "/signup", +].each { get _1, to: } +``` + +The `StaticController` reads the `index.html` from the `public` directory and serves it as the response for these routes: + +```ruby +# app/controllers/static_controller.rb +class StaticController < ApplicationController + def index + response.headers['Content-Type'] = 'text/html' + render plain: Rails.public_path.join('index.html').read, layout: false + end +end +``` + +### Cookies Support + +To manage cookies, the Rails API is configured to include `ActionController::Cookies`: + +```ruby +class ApplicationController < ActionController::API + include ActionController::Cookies +end +``` + +This allows cookies to be used even though Rails is running in API mode. + +## Frontend Development + +The frontend is a Vite-powered React SPA, and Bun is used as the package manager. The primary build scripts are defined in `frontend/package.json`: + +```json +{ + "name": "my-spa", + "packageManager": "bun@1.1.31", + "private": true, + "scripts": { + "prepare": "panda codegen", + "dev": "vite", + "build": "tsc -b && vite build", + "build:move": "bun run build && bun run move-assets", + "move-assets": "rsync -av --delete dist/index.html ../backend/public/ && rsync -av --delete dist/assets/ ../backend/public/assets/ && touch ../backend/public/assets/.keep", + "preview": "vite preview", + "graphql-codegen": "graphql-codegen" + } +} +``` + +Key commands include: +- `bun run dev`: Starts the Vite development server for live preview. +- `bun run build`: Builds the production assets for deployment. +- `bun run build:move`: Combines the build process and moves the build artifacts into the Rails public directory. + +## Running Locally + +1. **Install dependencies** + Make sure you have `bun` installed and run the following command from the root of the monorepo: + ```bash + bun install + ``` + +2. **Build the frontend** + Build the frontend and move the assets to the backend's public directory: + ```bash + bun run build:move + ``` + +3. **Build the Docker image for the Rails API** + Navigate to the `backend` directory and build the Docker image: + ```bash + cd backend && docker build -t my-spa . + ``` + +4. **Run the Rails server** + After the Docker image is built, you can run the server and test the integration locally.