React+Expressの環境構築

はじめに

Expressを試している際に、CORS問題に躓いたので試しに同一プロジェクト下で構築してみました。

✅ゴール
・Expressの理解を深める

✅環境
Windows

✅参考
💻
脱create-react-app ~ 真面目に express × react 環境を構築する~

こちらの記事をメインの参考としています。

リポジトリ

💻ExpressでReactを始める

うまくいかなかったので今度深掘りしてもいいかも。

ちゃんとリポジトリあるし。こちら

💻初級JavascriptフルスタックエンジニアのためのReactとExpressの同時開発チュートリアル(基本的なアプリ作成と同時開発環境構築編)

※ソースコードの紹介でCORS問題の解説はあまりなかった。

💻Nodeでサーバを立ててReactを使ったページでハロワをやってみる

これも気になっていたけどソースコードの紹介ベースで解説少なめだった。

💻reactとexpressをつなぐ

これは割と丁寧に解説あり。以下の書籍紹介もリンクにあった。

📚JavaScriptでのWeb開発 ~ Node.js + Express + MongoDB + ReactでWebアプリを開発しよう 〜 その1 〜(改訂版三版) Kindle版

これ別途読みたい。

フロントの環境構築

ディレクトリ作成

mkdir react-express

package.jsonの作成

npm init

webpack

👉webpack-dev-serverという開発サーバーを利用する。Reactは基本的にここで触る。

※HMRやProxyを提供する開発用Server

npm i -D webpack-cli webpack webpack-dev-server html-webpack-plugin

※-Dは–save-devの略でpackage.jsonに書き込まれる

babel

npm i -D babel-core babel-loader@7 babel-preset-env babel-preset-react

loader

npm i -D css-loader style-loader

React

npm i -S react react-dom

※–saveのショートハンド。V5以降はsaveがデフォルトで不要らしい。

src/client/index.htmlの作成

※コード割愛

src/client/index.jsの作成

※コード割愛

config/webpack.config.jsの作成

※コード割愛

.babelrcを作成

※コード割愛

package.jsonの編集

{
  "scripts": {
  "client": "webpack-dev-server --config ./config/webpack.config.js --open --mode development",
  "build": "webpack --config ./config/webpack.config.js --mode development"
  }
}

スクリプトの実行

npm run client

http://localhost:8081で確認。

ビルドでdistディレクトリ配下にコードが生成。※配布物という意味のdistribution

npm run build

🙄僕の場合はここですべてのフォルダをfrontディレクトリに移動しました。
⇒大きな間違いだった。。。

開発時はwebpack-dev-serverという開発サーバーを利用することでHMRが可能になるため
基本的にReactを触るときはwebpack-dev-server上で行う。
逆にexpressの方はwebpack-dev-serverは不要なため オートリロードさせることで
修正を反映。

本番環境ではHMRは不要なため webpack-dev-serverを使わない。
⇒expressから直接Reactを読み込んだhtmlに対してルーティングをかける。

サーバーの環境構築

express

npm i -S express

babel

npm i -D babel-preset-es2015 babel-preset-stage-0 babel-cli

.babrlrcの編集

{
  "presets": ["env", "react", "es2015", "stage-0"]
}

実行用パッケージ

npm i -D nodemon concurrently

※nodemonは対象ファイルを監視しnodeプロセスを再起動する

※concurrentlyは複数のコマンドを並列に実行できる

server.jsを作成

※コード割愛

/apiへのアクセスでJSONデータを返却。ポート番号は3000で指定している。

package.jsonへ以下追記

"scripts": {
  "server": "nodemon src/server/server.js  --exec babel-node",
  "dev": "concurrently \"npm run client\" \"npm run server\""

起動

npm run dev

ここまでのディレクトリ構造

ServerとFrontの連携

CORS問題を解消するためにProxyを開発サーバー側に立てる。

npm i -D webpack-merge

Proxyは開発時しか必要ないためdev専用にwebpack.config.dev.jsを作成

const merge = require('webpack-merge');
const webpackConfig = require('./webpack.config.js');

module.exports = merge(webpackConfig, {
  mode: 'development',
  devServer: {
    historyApiFallback: true,
    inline: true,
    open: true,
    host: 'localhost',
    port: 3000,
    proxy: {
      '/api/**': {
        target: 'http://localhost:8080',
        secure: false,
        logLevel: 'debug'
      }
    },
  }
})

webpack-dev-serverで/api/でアクセスした場合のみ3000に向けてリクエストするProxyが立ち上がる。

🙄コードを見るとProxy設定しているのが一目瞭然ですね!!

package.jsonの編集

※dev時のみ読み込むよう設定

"scripts": {
    "server": "nodemon src/server/server.js  --exec babel-node",
    "client": "webpack-dev-server --config ./config/webpack.config.dev.js",
    "build": "webpack --config ./config/webpack.config.js --mode production",
    "dev": "NODE_ENV=development concurrently \"npm run client\" \"npm run server\"",
    "start": "NODE_ENV=production npm run build && npm run server"
  },

serverでexpress立ち上げ
clientでwebpack-dev-serverの立ち上げ
buildでfrontコードのコンパイル
devで開発モード。expressサーバーとwebpack-dev-serverが立ち上がる
startで本番モード。frontコードをコンパイルしexpressを立ち上げ。

実行

npm run dev
~~~~抜粋
[HPM] Proxy created: /api/**  ->  http://localhost:8080

※このコマンドはnpm run clientとnpm run serverを同時に実行している。

http://localhost:3000/apiへアクセス。無事立てれていることを確認。

✅いろいろと試してみる

ためしに片方ずつコマンドを実行してみた。

npm run client

これでlocalhost:3000でReactを表示できる。

この状態でlocalhost:3000/apiへアクセスしても表示は何も変わらない。

同時にnpm run serverを実行するとapiでjsonデータが表示。

試しにnpm run clientを停止。

するとlocalhost:3000で表示されるのはビルド後のデータになる(最新の編集が反映されない)。

server.jsを確認すると以下の記述があるので当たり前ですね。

app.use(express.static(path.join('./', 'dist')));

app.get('*', function (req, res) {
  res.sendFile(path.join('./', 'dist', 'index.html'))
})

追って再度npm run clientするも表示は古いまま。

npm run serverを停止して更新すると最新の編集も反映され、リアルタイムで描画が更新される形に。

ここでnpm run devでもReactの古い描画がされることに気付いたのでためしにビルドして再確認すると描画も最新になった。

🙄イメージ、ExpressサーバーがReactサーバーより優先されている感じ。Express起動していない際はReactでHMRが機能するから変な感じ。確実にProxy周りの挙動だよな。

またindex.js側でfetchを活用してみる。

fetch('/api/').then(response => {
  console.log(response.json());
})

ビルド後再表示して確認。

ちゃんと読み込めている◎

躓いた点

✅npm run devができない

参考:node.js – NODE_ENVは、内部コマンドまたは外部コマンドとして認識されません

‘NODE_ENV’ は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

"dev": "NODE_ENV=development concurrently \"npm run client\" \"npm run server\"",

上記を以下のように編集

"dev": "SET NODE_ENV=development & concurrently \"npm run client\" \"npm run server\"",

SETと&を加えたところ解決。

おわりに

Proxyをちゃんと理解したい。

ただとりあえずExpress+Reactの環境構築(CORS問題もとりあえず解決)できたので、これでJavaScriptのみでDB接続やらいろいろできそう◎

すごいぞJavaScript!!

JavaScriptでのWeb開発 ~ Node.js + Express + MongoDB + ReactでWebアプリを開発しよう 〜 その1 〜(改訂版三版) Kindle版

次は上記を読んで理解を深めていこうかな。

⇒上記の本はReactの連携まで記載されているものがまだ出ていなかったのでステイ(なんてこった)

👇こんな記事も見つけた。

React開発時には、APIサーバーとReactアプリサーバーを別にして、プロキシを使うというベスト・プラクティス

React側でhttp-proxy-middlewareをインストールしてproxyの設定を行う。

npm install http-proxy-middleware

Proxyは開発環境でのみ配慮しなければいけないもの。

React+Expressで本番環境へデプロイ

この方はフロントとバックを別々のプロジェクトにして作成していくことをおすすめされてますね!

備忘録

・Hot Module Replacement (HMR)はwebpackの提供する仕組みで、画面の再描画すること無しにJSの変更をブラウザに適用してくれる開発ツール

コメントを残す