TypeScript × React-Tutorial: Tic-Tac-Toe / 三目並べ Deploy

この記事では，TypeScript × Reactで作成したサイトを簡単にDeployする方法を解説します．
自分が作成したプログラムとサイトは，以下になります．

https://github.com/tomtkg/React-Tutorial

https://tomtkg.github.io/React-Tutorial/

中身の詳細が気になる方は，以前の記事（[無印](https://qiita.com/tomtkg/items/a489006b85f5fb9896aa)，[Extra](https://qiita.com/tomtkg/items/380fc28d21e7b126f0b3)）を参照してください．

# はじめに
プログラムとサイトの要件は，以下の通りです．
* すべての情報は一般公開（public）で問題ない
* セキュリティや認証は考慮しない
* AWSやGCP等のクラウドサービスは利用しない
* プログラムはGitHubに置く
* サイトはGithubPagesで公開
* BuildとDeployはGitHubActionsを使う
* commitがpushされたらサイトを更新する

GitHubアカウントがあれば，サイトをDeployできます．
クラウドを利用しないので，無料でサイト公開できます．
なるべく内容を簡単にしたいため，認証等は考えません．

サイトをDeployするために必要なファイル，設定が必要となる箇所を中心に解説します．

# GitHubActions
BuildとDeployは，GitHubActionsを使います．
GitHubActionsは，`.github/workflows`ディレクトリにある`yml`ファイル，`yaml`ファイルの中身を読み取って実行します．
中身は，以下のように記述しました．
```yml: ci.yml
name: CI
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      - run: npm ci
      - run: npm run build
        env:
          PUBLIC_URL: /React-Tutorial
      - uses: actions/upload-pages-artifact@v2
        with:
          path: ./build
  deploy:
    needs: build
    permissions:
      id-token: write
      pages: write
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/deploy-pages@v2
        id: deployment
```
名前は，CIにします．
branchは特に指定せず，push時とpull_request時にjobsが動くようにします．
jobsは，buildとdeployの2つに分けています．
2つに分けることで，失敗した場合の問題箇所特定が容易になります．
buildに50秒，deployに10秒程度の時間がかかります．

buildは，最初に`npm run build`を動かすための環境を準備します．
そして，`npm run build`でbuildファイルを作成します．
このとき，`PUBLIC_URL`は必要に応じて変更します．
buildファイルは，Artifactsにuploadします．

deployは，build成功後に実行します．
こちらは，変更不要です．

動作の詳細は，GitHubのサイトから確認できます．

https://github.com/tomtkg/React-Tutorial/actions/runs/5838648205

# package.json
TypeScriptプロジェクトにある`package.json`を以下のように追記します．
```diff_json: package.json
{
+ "homepage": "https://tomtkg.github.io/React-Tutorial",
  "name": "react-tutorial",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
...
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
+   "postbuild": "cp build/index.html build/404.html",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
...
  },
  "browserslist": {
...
  }
}
```
サイトのpathを正しく認識するため，`homepage`を追加します．
`homepage`は，状況に応じて適切なURLを設定します．

Routerを利用したSingle Page Application（SPA）の場合，GithubPagesではページ遷移が失敗し，エラーが出ます．
SPAとGithubPagesの相性が悪いようですが，ここでは`404.html`を用意する簡単な対策で乗り切ります．
`404.html`は，`404 not found`エラー時の表示先です．
`index.html`を`404.html`としてコピーすることで，ページ遷移が成功$^※$します．

※`404.html`が原因で，検索エンジン等によるページ分析に問題が生じる可能性があります．
　アナリティクスが正しく集計できなかったり，SEO，検索順位で不利になる可能性があります．

# index.tsx
SPAの場合，`index.tsx`の変更が必要です．
例えば，`react-router-dom`を利用する場合，`index.tsx`を以下のように変更します．
```diff_tsx: index.tsx
  import './index.css';
...
  import React from 'react';
  import ReactDOM from 'react-dom/client';
+ import { BrowserRouter, NavLink, Route, Routes } from 'react-router-dom';
+ 
+ const View = () => { return ... }

  const root = ReactDOM.createRoot(
    document.getElementById('root') as HTMLElement
  );
  root.render(
    <React.StrictMode>
-     <App />
+     <BrowserRouter basename={process.env.PUBLIC_URL}>
+       <View />
+     </BrowserRouter>
    </React.StrictMode>
  );
```
`react-router-dom`は，`npm install react-router-dom`コマンドを打つと利用できます．
`View`では，`div`タグで囲んだ中で，`NavLink`, `Route`, `Routes`を使ったりしています．

大事なのは，`ci.yml`に記載した`PUBLIC_URL`を読み込む記述の追加です．
`<BrowserRouter basename={process.env.PUBLIC_URL}>`のように記述します．
`Router`にはURLを記載する方法があるはずなので，オプションを探して設定します．

# GitHubの設定
ファイルの用意ができたら，それらをGitHubリポジトリにpushします．
すべてが上手く設定できていたら，それだけでサイトがDeployされるはずです．
サイトのDeployに失敗した場合，GitHubリポジトリの設定変更が必要です．

GitHubリポジトリの設定は，web画面から操作できます．
まず，GithubActionsが動作していること，`X workflow runs`が表示されていることを確認します．
また，最新のworkflowのStatusがSuccessであることを確認します．
`settings/actions`や`settings/pages`を確認し，必要に応じて設定を変更します．
Actions permissions，Build and deployment，Custom domain等の設定変更でサイトのDeployができるはずです．

# 終わりに
TypeScript × Reactで作成したサイトを簡単にDeployする方法を解説しました．
記事執筆時（2023年8月）は，`actions/deploy-pages`v2.0.0が3か月前，`actions/upload-pages-artifact`v2.0.0が1か月前にReleaseされたばかりです．

https://github.com/actions/deploy-pages/releases/tag/v2.0.0

https://github.com/actions/upload-pages-artifact/releases/tag/v2.0.0

2つの`actions`は，内容や使い方が今後も変化していくと思います．

現在，buildファイルが[一定期間(最大400日)で削除](https://docs.github.com/ja/actions/learn-github-actions/usage-limits-billing-and-administration#artifact-and-log-retention-policy)されてサイトが見れなくなる気がしています．
この問題は，GithubActionsの発展，進化で解消されることを期待しています．

以上で，「TypeScript × React-Tutorial: Tic-Tac-Toe / 三目並べ」の自習を修了します．

関連記事:

https://qiita.com/tomtkg/items/a489006b85f5fb9896aa

https://qiita.com/tomtkg/items/380fc28d21e7b126f0b3