ReactでサブディレクトリにWebアプリを置くときの設定まとめ


# 利用シーン

Reactでフロントを作ったとき、`https://site.domain`ではなく、
`https://site.domain/sub_dirctory`に`index.js`や`index.html`を設置する場面。
そのままでは、大量の`contents`が`404 Not Found`になります。

たくさんURLを書き換えるのは骨が折れるので、数か所の変更で済む方法はないのか？
情報源がいろいろあって分かりにくかったので、１ページにまとめました。

※下記で`./`はプロジェクトルートディレクトリを指します。

# package.jsonを設定

`./package.json`に`"homepage": "/sub_dirctory/"`を追加します。

```diff_jsondoc:./package.json
{
  "name": "project001",
  "version": "0.1.0",
  "private": true,
// -- any things
// -- any things
+  "homepage": "/sub_dirctory/"
}
```

# historyを追加

https://create-react-app.dev/docs/deployment/#:~:text=%22start_url%22%3A%20%22.%22%2C-,Building%20for%20Relative%20Paths

Routingを行っているjsファイルにて、Router系のJSXのpropsである`history`に設定を行います。
この時、ライブラリ`history/createBrowserHistory`が必要です。
`history`を使っていない場合は、ここで新規にインストールします。
npmを使ってインストールする場合のコマンドです。

```posh:terminal
npm install history
```

npmではなくyarnの場合です。

```posh:terminal
yarn add history
```

次に、該当箇所に変更を入れます。

```jsx:./src/app.js
// -- any things
import MiniApp_001 from 'miniapp_001';
import MiniApp_002 from 'miniapp_002';
import { Router, Route, Switch } from 'react-router-dom';
import { createBrowserHistory } from 'history';
// -- any things
const customizedhistory = createBrowserHistory({ basename: '/sub_dirctory' });
// -- any things
class App extends React.Component {
    render() {
        return (
// -- any things
            <Router history={customizedhistory}>
                <Switch>
                    <Route exact path="/" component={MiniApp_001} />
                    <Route exact path="/test" component={MiniApp_002} />
                    <Route component={NotFound} />
                </Switch>
            </Router>
// -- any things
        );
    }
}
export default App;
```

上から順に説明していくと、
まず、先ほどインストールした`history`から`createBrowserHistory`をインポートします。

```jsx
import {createBrowserHistory} from "history"
```

次に、`createBrowserHistory`を使って、`/subdirectory`を指定するためのオブジェクト`customizedhistory`を用意します。

```jsx
const customizedhistory = createBrowserHistory({ basename: '/sub_dirctory' });
```

JSXオブジェクトである`Router`の`props`に、`history`があります。この`history`の値に`customizedhistory`を設定します。

```jsx
<Router history={customizedhistory}>
```

この例では`Router`を用いていますが、他に`BrowserRouter`や`HashRouter`、`MemoryRouter`、`StaticRouter`があります。いずれも同様に設定可能です。

https://reactrouter.com/en/routers/picking-a-router#picking-a-router

ちなみに、JSXのネストの根っ子にRouterは１個あればいいです。`<Switch/>`設置するたびに`<Router/>`設置すると沼にハマります。

# .htaccessを設定する

Apache の場合にはhtaccessの設定を必要とします。

```:./public/.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ ./index.html [QSA,L]
```

#### Rewrite系構文のドキュメント

- [RewriteEngine](http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#RewriteEngine)

- [RewriteCond](http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#RewriteCond)

- [RewriteRule](http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#RewriteRule)

http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html

# nginx.confを設定する

nginxの場合は`nginx.conf`に下記設定を追記する必要があります。

```conf:nginx.conf
location ^~ /sub_dirctory{
   alias /var/www/project001/build;
   try_files $uri $uri/ /sub_dirctory/index.html;
}
```

# まとめ

多くのWebフレームワークでは、ドメインのルートに設置する前提で設計されています。もちろんReactも例外ではありません。デフォルトでは`/`に設定されています。しかし、いくつか設定すれば簡単に変更できます。

多くのWebフレームワークがDRYの原則から生まれたようなもの。これが出来るのは当たり前品質かもしれませんね。少しぐらいの誤差は吸収できるように、ロバストなコードを使えばサボれる。サボりは大切です。

**Excelsior!**