ReactをDockerで開発してGithub ActionsでGithub Pagesに自動で公開するReactアプリ開発用のテンプレートリポジトリ

# これはなに？
Reactで開発をするときのオレオレな開発テンプレートリポジトリです。このリポジトリをReactアプリ開発の初期環境として使用することで、Dockerベースの開発環境が用意され、master branchにmergeされるとGithub Actionsが動きbuildとGithub Pagesへの公開が自動で行われます。

- [テンプレートのGithubリポジトリ](https://github.com/k8shiro/ReactGithubTemplate)

# 使い方
[テンプレートリポジトリ](https://github.com/k8shiro/ReactGithubTemplate)を`git clone`します。
※ forkした場合、Github Actionsが動作しない。

```
git clone https://github.com/k8shiro/ReactGithubTemplate
```

clone後、gitのremoteを自分のgithubのリポジトリのURLに変更します。

```
git remote set-url origin <自分のgithubのリポジトリのURL>
```

この後はdevelopブランチで開発を行い、開発が終了したらmasterブランチにmergeしましょう

## 新しくReactアプリを作成する場合

既にサンプルのmy-appアプリが作成されているのでこれを削除し、以下のコマンドでcreate-react-appを実行します。

```
rm -rf app/my-app
docker-compose run --rm node sh -c "create-react-app new-my-app"
# new-my-appを自分のアプリ名に変える
```

docker-compose.ymlのenvironmentのREACT_APP_NAMEを自分のアプリ名に変更


```
version: "3"
services:
  node:
    build:
      context: ./app
    environment:
      - NODE_ENV=production
      - REACT_APP_NAME=my-app # ここのmy-appを修正
    volumes:
      - ./app:/usr/src/app
    ports:
      - "3000:3000"
```

また、app/my-app/package.jsonにhomepageを追加します。

```
{
  "homepage": ".", # ここを追加
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
...
```

## 作成済みのアプリを動かす場合(初回のみ)

- packageのインストールが必要

```
docker-compose run --rm --service-ports node ash -c "cd \$REACT_APP_NAME; yarn install"
```

## アプリケーションの開発を行う

- 開発サーバーを立ち上げる

```
docker-compose run --rm --service-ports node ash -c "cd \$REACT_APP_NAME; yarn start"
```

ホストマシンの3000ポートでアプリケーションが起動します。

- コードを修正する

開発サーバーが起動している状態でホストマシン上で'app/my-app'内を修正すればビルドされます。

- パッケージを追加する

```
docker-compose run --rm  --service-ports node ash -c "cd \$REACT_APP_NAME; yarn add package-name"
```


## Github Pagesが公開されない

github pagesへの反映には若干時間がかかるようですが、公開されない場合以下を試すと表示されることがありました。

リポジトリのSettingsのGithub Pagesで使用するブランチを指定できます。これを

- デフォルトのgh-pagesからmasterに変更
- masterからgh-pagesに戻す

を行うと公開されました。

# リポジトリの解説
## .github/workflows/main.yml
Github Actionsの設定ファイルです。

```
name: Build React APP

on:
  push:
    branches:
      - master

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: build app
      run: |
        docker-compose run --rm node ash -c 'cd $REACT_APP_NAME; npm install; yarn build; cp -rf build /usr/src/app/; ls;
    - uses: crazy-max/ghaction-github-pages@v1
      with:
        target_branch: gh-pages
        build_dir: app/build
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

- masterブランチへのpushをトリガーとして動作します。
- `docker-compose run --rm node ash -c 'cd $REACT_APP_NAME; npm install; yarn build; cp -rf build /usr/`ではReactのアプリケーションのbuildを行った後、buildディレクトリを`/usr/src/app/`(ホスト側の./appがマウントされている)にコピーしています。
- ホスト側にコピーされた`./app/build`ディレクトリをgh-pagesブランチにpushし、Github Pagesに公開されます。
    - Github ActionsのMarket# これはなに？
- [ReactをDockerで開発してGithub ActionsでGithub Pagesに自動で公開するReactアプリ開発用のテンプレートリポジトリ](https://github.com/k8shiro/ReactGithubTemplate)

Reactで開発をするときのオレオレな開発テンプレートリポジトリです。このリポジトリをReactアプリ開発の初期環境として使用することで、Dockerベースの開発環境が用意され、master branchにmergeされるとGithub Actionsが動きbuildとGithub Pagesへの公開が自動で行われます。

# 使い方
テンプレートリポジトリを`git clone`します。
※ forkした場合、Github Actionsが動作しない。

```
git clone https://github.com/k8shiro/ReactGithubTemplate
```

clone後、gitのremoteを自分のgithubのリポジトリのURLに変更します。

```
git remote set-url origin <自分のgithubのリポジトリのURL>
```

この後はdevelopブランチで開発を行い、開発が終了したらmasterブランチにmergeしましょう

## 新しくReactアプリを作成する場合

既にサンプルのmy-appアプリが作成されているのでこれを削除し、以下のコマンドでcreate-react-appを実行します。

```
rm -rf app/my-app
docker-compose run --rm node sh -c "create-react-app new-my-app"
# new-my-appを自分のアプリ名に変える
```

docker-compose.ymlのenvironmentのREACT_APP_NAMEを自分のアプリ名に変更


```
version: "3"
services:
  node:
    build:
      context: ./app
    environment:
      - NODE_ENV=production
      - REACT_APP_NAME=my-app # ここのmy-appを修正
    volumes:
      - ./app:/usr/src/app
    ports:
      - "3000:3000"
```

また、app/my-app/package.jsonにhomepageを追加します。

```
{
  "homepage": ".", # ここを追加
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
...
```

## 作成済みのアプリを動かす場合(初回のみ)

- packageのインストールが必要

```
docker-compose run --rm --service-ports node ash -c "cd \$REACT_APP_NAME; yarn install"
```

## アプリケーションの開発を行う

- 開発サーバーを立ち上げる

```
docker-compose run --rm --service-ports node ash -c "cd \$REACT_APP_NAME; yarn start"
```

- コードを修正する

この状態でホストマシン上で'app/my-app'内を修正すればビルドされます。

- パッケージを追加する

```
docker-compose run --rm  --service-ports node ash -c "cd \$REACT_APP_NAME; yarn add package-name"
```


## Github Pagesが公開されない

github pagesへの反映には若干時間がかかるようですが、公開されない場合以下を試すと表示されることがありました。

リポジトリのSettingsのGithub Pagesで使用するブランチを指定できます。これを

- デフォルトのgh-pagesからmasterに変更
- masterからgh-pagesに戻す

を行うと公開されました。

# リポジトリの解説
## .github/workflows/main.yml
Github Actionsの設定ファイルです。

```
name: Build React APP

on:
  push:
    branches:
      - master

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: build app
      run: |
        docker-compose run --rm node ash -c 'cd $REACT_APP_NAME; npm install; yarn build; cp -rf build /usr/src/app/; ls;
    - uses: crazy-max/ghaction-github-pages@v1
      with:
        target_branch: gh-pages
        build_dir: app/build
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

- masterブランチへのpushをトリガーとして動作します。
- `docker-compose run --rm node ash -c 'cd $REACT_APP_NAME; npm install; yarn build; cp -rf build /usr/`ではReactのアプリケーションのbuildを行った後、buildディレクトリを`/usr/src/app/`(ホスト側の./appがマウントされている)にコピーしています。
- ホスト側にコピーされた`./app/build`ディレクトリをgh-pagesブランチにpushし、Github Pagesに公開されます。
    - Github ActionsのMarketplaceで公開されているワークフローを使用(https://github.com/marketplace/actions/github-pages)

## dockre-compose.yml

この環境ではReactアプリはDockerコンテナの内部で動作します。この時の基本的な設定はdocker-compose.ymlで管理しています。

```
version: "3"
services:
  node:
    build:
      context: ./app
    environment:
      - NODE_ENV=production
      - REACT_APP_NAME=my-app
    volumes:
      - ./app:/usr/src/app
    ports:
      - "3000:3000"
```

`environment`で`REACT_APP_NAME`をコンテナ内の環境変数で渡すことで`docker-compose run`でReact APPにyarnコマンド等を実行するときに利用できるようにしています。