create-react-app を Rails プロジェクトの下でやる

初投稿です。お手柔らかに。

## やりたいこと

ただ手軽に Rails 上で React を使ってみたい。
 webpacker やら sprockets やら頭痛くなるしそれって結局なんだかモノリシックな感じがする（気分的に）。

とりあえずSPAで良いならcreate-react-appで十分なはずではないか。

欲しいのはビルドされた index.html と *.js と *.css。
となればただの静的ファイルなわけで、先にビルドしてpublic に置いて WEB サーバに配信を任せればいいじゃん。

## つまり（やること）

React アプリのビルド吐き出し先を public/配下に。
create-react-app で生成されたものを eject（隠しファイルを展開？）してちょろろっと設定書き換えるだけ。
それだけ。

## Rails アプリの生成

一応細かく書きますが、それぞれやりやすいようにやってください。
bundler はグローバル（rbenv）にインストール済み。Rails はこれからプロジェクトローカルにインストール：

```bash
mkdir cra-on-rails
cd cra-on-rails/
ruby -v # => ruby 2.5.3p105
bundle init
```

Gemfile の Rails のコメントアウトを解除：

```ruby:Gemfile
# gem "rails"
gem "rails"
```

Rails のインストール：

```bash
bundle install --path vendor/bundle
# vendor/bundleにインストールされるので後々gitignoreへの追記を忘れずに
```

Rails アプリの生成：

```bash
bundle exec rails -v # => Rails 5.2.2
bundle exec rails new . --api
bin/rails server
```

localhost:3000 にアクセス：
**Yay!**

確認したらサーバは終了させておく（Ctrl-C）。

## create-react-app

React プロジェクトを **Rails プロジェクト直下** に置きたい。
create-react-app コマンドはインストール済み。

```bash
create-react-app client
cd client/
yarn start
```

自動的に localhost:3000 に飛ばされるてぐるぐるぐるぐるなってればオーケー。
ただ、Rails の dev サーバと React の dev サーバが同じポートを使っていることは気にしておく。
（この記事では何もしない）

## eject

create-react-app で作られたプロジェクトって、隠された設定ファイルやらスクリプトやらいっぱいあるらしいです。
それを見えるようにするのが eject。

```bash
git commit -am 'create-react-app' 
# コミットしておかないとejectできない

# 以下 client/ 下で
yarn eject
```

なんかいっぱい出てくる。

実はここで `yarn run start` するとエラーになる。
詳しくは知らないけど `node_modules` を再インストールすればいける。

```bash
rm -rf node_modules/
yarn install
```

これで `yarn run start` すればぐるぐるぐるぐるに行けるはず。

## build の準備

`yarn run build` で出来るんですが、
デフォルトだと出力先が React アプリの build/以下。
これを Rails 側の public にしたい。

編集すべきファイルは `(client)/config/paths.js`
下の方に

```javascript:config/paths.js
  appBuild: resolveApp('build'),
```

とあるが、この 'build' を好きな場所に変えてやれば良い。
今回は、

```javascript:config/paths.js
  appBuild: resolveApp('../public/myapp'),
```

とした。
あと一つ、 `package.json` に　`homepage` の設定を追加する。
これは `index.html` やらに埋め込まれる、各アセットへのリンクの接頭辞になるらしい（多分）。
今回は `localhost:3000/myapp` としたいので、 `"homepage": "/myapp"` を追加してやる。
json の構造のトップレベルならどこでも良いと思う（多分）。

```json:package.json
{
  ...
  "private": true,
  "homepage": "/myapp",
  ...
}
```

てな感じ。

## build してみる

`client` ディレクトリにいること。

```bash

yarn build
```

終わったら、

```bash

$ ls ../public/myapp/
asset-manifest.json
favicon.ico
index.html
manifest.json
precache-manifest.838fcce3524f688b979fcaf8b5daf742.js
service-worker.js
static
```

みたいになってるはず。Rails 側で起動してみる。

```bash

cd ..
bin/rails server
```

http://localhost:3000/

Yay!

http://localhost:3000/myapp

ぐるぐるー。

## なんとなく heroku にデプロイしてみる、の準備

もうそのまま heroku にアップすれば問題ないのだが、ひとつだけ、
Heroku （production 環境?）では root にアクセスした時 Yay! が表示されないのでリダイレクトだけ設定しておく。

Rails のディレクトリで作業。

```bash

bin/rails generate controller home index
```

```ruby:app/controllers/home_controller.rb
class HomeController < ApplicationController
  def index
    redirect_to '/myapp'
  end
end
```

```ruby:config/routes.rb

Rails.application.routes.draw do
  root to: 'home#index'
end
```

`bin/rails server` で確認どうぞ。

あとはもう`git commit` して`heroku create` して`git push heroku master` して `heroku open` でどうぞ。

## やり残し（また書くかも）

- API を全く使っていない。  
- 同じオリジンだけど devise で認証できるか試してない。  
- react 側の dev サーバのポート変えてプロキシ差し込んで API と通信しつつもホットリロードな感じの開発エクスペリエンスを得られるか試してない。