LoginSignup
3
2

More than 1 year has passed since last update.

Node.js Express + React の Proxy 設定について

Posted at

この記事について

Node.js Express をキャッチアップし、アウトプットしようと簡単なWebアプリを作成したとき、Proxyの設定に少々つまづいたので備忘録。

やりたいこと

  • Github APIを利用し、Githubのクローンを作成したい(ユーザー情報閲覧、フォロー、フォロワー、リポジトリ、ユーザー検索機能のみ)。
  • ServerサイドでAPIを作成(Node.js Express)。
  • ClientサイドはReactで作成。

バージョン

$ node -v
v14.17.0

$ npm -v
6.14.13

express: 4.18.1
react: 18.1.0

想定

  • React project ・・・http://localhost:3000
  • Express project ・・・http://localhost:5000

ユーザーはhttp://localhost:3000にアクセスすることでReactによって描画されたブラウザを閲覧できる。
アプリケーション内でGithubユーザーの検索や、フォロワー情報の取得などする際は、Express側で取得したGithub APIの情報をclient側へ渡す。
client(React)側から直接外部APIの呼び出しは行わない(通常client側からDBアクセスはしないことを想定)。
app/client/package.json"proxy"Keyを設定し"http://localhost:5000"をValueとすることでExpressで作成したAPIサーバーへアクセスできる。

app/client/package.json
{
  "name": "client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^13.2.0",
    "@testing-library/user-event": "^13.5.0",
    "react": "^18.1.0",
    "react-dom": "^18.1.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "proxy": "http://localhost:5000"  // この行を追加
}

処理の流れ

フォロワー一覧取得の場合

  1. client側からhttp://localhost:5000/api/v1/followersへGETリクエスト。
  2. server側でGithub API https://api.github.com/users/{userName}/followersへGETリクエスト。
  3. 受けっとったレスポンスを必要な情報のみに整形。
  4. 結果をclientへ返す。
  5. Reactでスタイリングし、ブラウザへ描画。

ディレクトリ構成

app
 ├── client
 │      ├── node_modules
 │      ├── src
 │      │     ├── app
 │      │     │    └── App.jsx
 │      │     ├── index.css
 │      │     └── index.js
 │      └── package.json
 │
 ├── node_modules
 ├── server
 │        └── server.js // Express で API 作成
 └── package.json

実行

/app/package.jsonのコマンドを実行

app/package.json
"scripts": {
    "client-install": "cd client && npm install",
    "client": "npm start --prefix client",
    "server": "nodemon server/server.js",
    "dev": "concurrently \"npm run server\" \"npm run client\""
}
$ pwd
/app

$ npm run dev

実行エラー

コンソールエラー

[1] Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
[1]  - options.allowedHosts[0] should be a non-empty string.
[1] npm ERR! code ELIFECYCLE
[1] npm ERR! errno 1
[1] npm ERR! client@0.1.0 start: `react-scripts start`
npm ERR! Exit status 1
[1] npm ERR! 
[1] npm ERR! Failed at the client@0.1.0 start script.
[1] npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
[1] 
[1] npm ERR! A complete log of this run can be found in:
[1] npm ERR!     /Users/.npm/_logs/2022-05-21T03_09_52_961Z-debug.log
[1] npm ERR! code ELIFECYCLE
[1] npm ERR! errno 1
[1] npm ERR! react-express-api@1.0.0 client: `npm start --prefix client`
[1] npm ERR! Exit status 1
npm ERR! 
[1] npm ERR! Failed at the react-express-api@1.0.0 client script.
[1] npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
[1] 
[1] npm ERR! A complete log of this run can be found in:
[1] npm ERR!     /Users/.npm/_logs/2022-05-21T03_14_06_437Z-debug.log
[1] npm run client exited with code 1

指定されたログファイル

/Users/.npm/_logs/2022-05-21T03_14_06_437Z-debug.log
〜〜 省略 〜〜
14 verbose pkgid react-express-api@1.0.0
15 verbose cwd /Users/project/app
16 verbose Darwin 21.4.0
17 verbose argv "/Users/.nodebrew/node/v14.17.0/bin/node" "/Users/.nodebrew/current/bin/npm" "run" "dev"
18 verbose node v14.17.0
19 verbose npm  v6.14.13
20 error code ELIFECYCLE
21 error errno 1
22 error react-express-api@1.0.0 dev: `concurrently "npm run server" "npm run client"`
22 error Exit status 1
23 error Failed at the react-express-api@1.0.0 dev script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 1, true ]

client側のみ立ち上げてみる

$ pwd
/app/client

$ npm run start

コンソールエラー

Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
 - options.allowedHosts[0] should be a non-empty string.

When specified, "proxy" in package.json must be a string.
[1] Instead, the type of "proxy" was "object".
[1] Either remove "proxy" from package.json, or make it a string.

昨日までこの設定で動かして開発していたのに、突然動かなくなり頭の中が ???? でした。

解決法

app/client/package.jsonに設定した"proxy"を削除

app/client/package.json
〜〜 省略 〜〜
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "proxy": "http://localhost:5000"  // この行を削除
}

新たにhttp-proxy-middlewareというパッケージを追加し、app/client/src/setupProxy.jsというファイルを作成します。

$ pwd
/app/client

$ npm install http-proxy-middleware
app/client/src/setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = (app) => {
	app.use(
		'/api/*',
		createProxyMiddleware({
			target: 'http://localhost:5000',
			changeOrigin: true,
		})
	);
};

create-react-appが、自動的にsrc/setupProxy.jsこのファイルを探すので、importなどは不要とのこと。

修正後ディレクトリ構成

app
 ├── client
 │      ├── node_modules
 │      ├── src
 │      │     ├── app
 │      │     │    └── App.jsx
 │      │     ├── index.css
 │      │     ├── index.js
 │      │    └── setupProxy.js  // 新たに追加
 │      └── package.json
 │
 ├── node_modules
 ├── server
 │        └── server.js
 └── package.json

動作確認

まずはclient側だけ立ち上げてみる

$ pwd
/app/client

$ npm run start

無事成功!

client側、 server側同時に立ち上げてみる

$ pwd
/app

$ npm run dev

無事成功!!

まとめ

途中にも書きましたが、前日まで動いていたのに、突然動かなくなった理由はわかりません。
しかし、この修正でより安定した開発ができそうです。
原因がわかる方いらっしゃいましたら、ご教授ください。
また、今Webアプリの全貌は別記事にまとめる予定ですので、よろしければそちらもご覧ください。

参考にしたサイト

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2