Reactをexpressにホストする


やり方を聞かれて調べたのでメモ。
react-router-domでルーティングされているページをbuildしてexpressにホストしたい。

Reactでの作業

とりあえず何でもいいのですが、react-router-domで最低限のルーティングを設定します。

簡易仕様

  • / → Home.js
  • /about → About.js
  • それ以外だと、Page not found.を表示。

プロジェクトの作成

とりあえずcreate-react-appでプロジェクトを作成。

npx create-react-app react-test
cd react-test

最低限のルーティングを設定したいのでreact-router-domのインストール。

npm install react-router-dom

Home.jsとAbout.jsを生成。

touch src/Home.s src/About.js

Home.js

Home.jsの実装。Homeと表示し、About.jsへのリンクがあるだけ。

Home.js
import { Link } from "react-router-dom";

const Home = () => {
    return (
        <div>
            Home<br/>
            <Link to="/about">Aboutへ</Link>
        </div>
    );
}

export default Home;

About.js

Aboutと表示しHome.jsへのリンクがあるだけ。

About.js
import { Link } from "react-router-dom";

const About = () => {
    return (
        <div>
            About<br/>
            <Link to="/">Homeへ</Link>
        </div>
    );
}

export default About;

App.js

ルーティングの設定。/でも/aboutでもなければPage not foundを表示。

App.js
import { BrowserRouter, Switch, Route } from "react-router-dom";

import Home from "./Home";
import About from "./About";

const App = () => {
  return (
    <BrowserRouter>
      <Switch>
        <Route path="/" exact component={Home} />
        <Route path="/about" exact component={About} />
        <Route render={()=><p>Page not found.</p>}/>
      </Switch>
    </BrowserRouter>
  );
}

export default App;

動作確認

npm startで動作確認。 http://localhost:3000。

npm start

build(本番用ファイル生成)

今回の肝はbuildしたファイルがexpressで動くかなのでbuild。

npm run build

buildファイルが作成され、中にbuild結果が出力される。index.htmlを始めとする各種ファイルが生成される。

Express側での作業

上記で生成されたファイル群をexpressの静的ファイルホスティングで正常に動作させるのがゴール。

expressのインストールと作業場の作成

expressをインストールし、reactのプロジェクトフォルダ中にnodeフォルダを作る(わけてもいい。めんどいのでそうしているだけ)。そして、index.jsを生成。

npm install express
mkdir node
touch node/index.js
cd node

実装

index.jsを実装していく。

index.js
const path = require("path");
const express = require("express");
const app = express();

//ミドルウエアでstaticパスを追加(ただ、これだけだと直アクセスや無いpathだと動かない)
app.use(express.static(path.join(__dirname, "..", "build")));

//これを追加(全てをindex.htmlにリダイレクト。いわゆるrewrite設定)
app.use((req, res, next) => {
    res.sendFile(path.join(__dirname, "..", "build", "index.html"));
});

app.listen(3001, () => {
    console.log("server started on port 3001");
});

ポイント

動作のポイントは2つ。

静的ファイルの場所

まず、静的フォルダを設定する。
これだけで実は http://localhsot:3001にアクセスすると動きます。が、これだけでは不十分。

app.use(express.static(path.join(__dirname, "..", "build")));

/を経由せず、ダイレクトに/aboutや/xxxとかにアクセスするとエラーとなる(表示されない or Not foundとならない)。

全てのリクエストをbuild/index.htmlへ

これらを処理するには全てのリクエストをindex.htmlに処理させる必要がある。
一般的なWebサーバではRewirte処理などを行うがExpressでは以下のようにする。

app.use((req, res, next) => {
    res.sendFile(path.join(__dirname, "..", "build", "index.html"));
});

実行

では動作確認してみる。

node index.js

確認