React.jsのIISデプロイ方法

## はじめに
reactのIISデプロイ方法に難儀したので備忘録として残します。
投稿久々～～～～((´∀｀))ｹﾗｹﾗｹﾗｹﾗｹﾗｹﾗｹﾗｹﾗｹﾗｹﾗｹﾗｹﾗｹﾗｹﾗｹﾗｹﾗ

## 環境
- Windows Server 2016
- IIS: 10.0.14393.0
- url-rewite: 2.0
- node: v16.15.0
- React: v18.1.0
- react-router-dom: 6.3.0


## プロジェクトの作成
`create-react-app`でreactのプロジェクトを作ります。

```
npx create-react-app deploy-app
```

これをbuildして、デプロイモジュールを作ります。

```
cd deploy-app
npm run build
```

buildが完了したら`build`フォルダにモジュール一式作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/90ad4763-f16e-7794-aa80-2dd8d7e8b557.png)


## IISデプロイ その1
IISを開いてサイトを追加していきます。
まずはアプリケーションプールを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/7b3ee2db-dd37-1e3b-46e9-6f70686492f4.png)

名前は`react-deploy`で行きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/ea5bad31-ee14-b6a1-c036-c5d68a11839f.png)

詳細設定はこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/fd9f8d4c-ffb3-17e5-80cb-a6d0c2889905.png)

次に先ほど作成した`build`フォルダを`C:\inetpub\wwwroot`にコピーして
名前を`react-deploy`にしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/6788e589-e0cd-3456-43a2-6c9c6424ea8c.png)


次にWebサイトの追加を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/4b0f7757-cc0d-a22e-84e8-a5ff6ea53f44.png)


- サイト名 `react-deploy`
- 物理パス `C:\inetpub\wwwroot\react-deploy`
- バインドポート `8080`
※ポート番号は気分で変えてます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/8abf6b31-3e0e-564c-b215-e00d3c3d187a.png)

`デプロイしたマシンのIPアドレス:8080`にアクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/c821dbbf-6e19-e405-0efb-720c78d5eab1.png)
デプロイできました。

他のマシンから覗くと繋がらなかったのでtcpポートを開放しておきます。
素直にポート80にしておけばよかったと思いました。

`コントロールパネル > システムとセキュリティ > Windows ファイアウォール > 詳細設定`　を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/6c8d2c24-4dcc-8ec1-99d1-b7e2e7fbc967.png)

`受信の規則`を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/8a061cf9-512d-2108-4e76-b25cc57552d5.png)

新しい規則を作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/2c438663-7b1f-53e6-0192-49afddcc3699.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/661d51b9-c2b5-cf55-b0d8-949de3fa63a1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/5fb52c51-6e57-3039-f06f-80fb7a7013cb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/7dc33cef-90c9-e12c-5c5d-e07550618ca0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/5984df90-25a4-49b7-8f6e-b7fac7bd92f1.png)

これで外から繋がるようになりました。
さくっと試すだけならファイアウォール全部止めちゃってもいいと思います。
自己責任にはなりますが。。。

## react-router-domのインストール
これだけだと物足りないので次にroutingも正常に動くか見ていきます。

まずは`react-router-dom`をインストールします。
```
cd ../
npm install react-router-dom@6.3.0
```

ものすごく簡単なページを作ります。
src直下に`pages`フォルダを作成し、`Home.jsx`と`Page1.jsx`と`Page2.jsx`を作成します。

```pages/Home.jsx
import React from "react";
import { Link } from "react-router-dom";

export function Home() {

  return (
    <div className="Home">
      Home画面です。
      <nav>
        <ul>
          <li><Link to="page1">Page1</Link></li>
          <li><Link to="page2">Page2</Link></li>
        </ul>
      </nav>  
    </div>
  );
}
```

```pages/Page1.jsx
import React from "react";
import { Link } from "react-router-dom";

export function Page1() {

  return (
    <div className="Page1">
      Page1
      <nav>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/page2">Page2</Link></li>
        </ul>
      </nav> 
    </div>
  );
}
```

```pages/Page2.jsx
import React from "react";
import { Link } from "react-router-dom";

export function Page2() {

  return (
    <div className="Page2">
      Page2
      <nav>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/page1">Page1</Link></li>
        </ul>
      </nav> 
    </div>
  );
}
```

```App.js
import './App.css';
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { Home } from './pages/Home';
import { Page1 } from './pages/Page1';
import { Page2 } from './pages/Page2';

function App() {
  return (
    <div className="App">
     <BrowserRouter>
      <Routes>
        <Route index element={<Home />} />
        <Route path="page1" element={<Page1 />} />
        <Route path="page2" element={<Page2 />} />
      </Routes>
    </BrowserRouter>
    </div>
  );
}

export default App;

```

一応、動作確認しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/47cbeb2a-d0c3-51b1-e801-40b60a18f606.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/5c53179b-d675-76c5-6f99-ebc8e80ced6e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/ecaaae3c-20ad-87e7-da55-8c5cf7019b8f.png)

動いてそうです。
モジュールを作り直してデプロイしなおします。
念のため、アプリケーションプールを停止してから`C:\inetpub\wwwroot\react-deploy`の中身を入れ替え、サイトを開始します。
一応動いていそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/f408c6b7-03fd-8595-5e3e-0dbd152abf93.png)

と、思いきやブラウザから`デプロイしたマシンのIPアドレス:8080/page1`にアクセスすると404エラーが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/0bae4a07-824a-8dd4-3a34-b1a688156c54.png)
プログラムからだと正常に動いているような気もします。

ReactはSPAなのでindex.htmlを読む分にはうまくいくらしいですが、直リンクだとリソースがないと怒られるらしいです。
stackoverflowとかを見ると[url-rewriteモジュール](https://www.iis.net/downloads/microsoft/url-rewrite)を使えと書いてあります。

## url-rewriteのインストール
[url-rewriteモジュール](https://www.iis.net/downloads/microsoft/url-rewrite)からインストーラーをダウンロードして、インストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/7b5ec6c7-f241-7c77-f019-69f3166632e7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/94760b90-6f1d-52bb-1132-113a6e33f77a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/37bbf463-bfeb-736e-abc4-0debdb5862a5.png)

## web.configの配置
ビルドモジュール直下の所に`web.config`を配置する必要があるみたいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/8d876c82-8f08-5bca-b473-6d71e9bef359.png)

内容はこんな感じです。
```xml: web.config
<?xml version="1.0"?>  
<configuration>  
    <system.webServer>  
        <rewrite>  
            <rules>  
                <rule name="React Routes" stopProcessing="true">  
                    <match url=".*" />  
                    <conditions logicalGrouping="MatchAll">  
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />  
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />  
                        <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />  
                    </conditions>  
                    <action type="Rewrite" url="/" />  
                </rule>  
            </rules>  
        </rewrite>  
    </system.webServer>  
</configuration>     
```

## IISデプロイ その2
再度、アプリを再起動し、ブラウザから直リンクでアクセスしてみると見えることができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/fff0e3bf-ee7d-681a-3888-1ca9c45fdc56.png)

## 参考URL
以下のURLを参考にしました。有益なサイト達に感謝します。
[react-routerを使ったアプリケーションでURL直叩き(or F5)すると404になる](https://dev-daikichi.hatenablog.com/entry/2019/04/17/144159)
[Reactで直接URLをたたくと404になる時の対応](https://qiita.com/yakipudding/items/78e68ef31e55f559c0dc)
[Deploy React Application on IIS Server](https://www.letsreact.org/deploy-react-application-on-iis-server/)
[How To Deploy React Application On IIS Server](https://www.c-sharpcorner.com/article/how-to-deploy-react-application-on-iis-server/)
[how to prevent iis default not-found page and show a custom reactjs not-found page](https://stackoverflow.com/questions/70486515/how-to-prevent-iis-default-not-found-page-and-show-a-custom-reactjs-not-found-pa)