masalibの日記

システム開発、運用と猫の写真ブログです

reactとexpressをつなぐ

社内の勉強会でreactを勉強しています

サンプルをもとに作っているのですが
reactとexpressをつなぐ所が動かず・・・泣きそうになっています

何回目なのかわからないのですが1から作り直す事にしました

別のツールでつくれる事がわかりました

masalib.hatenablog.com

事前作業

express-generatorとcreate-react-appをインストールします

$ npm install -g express-generator
$ express --version
# 4.16.0

$ npm install -g create-react-app
$ create-react-app --version 
# 1.5.2

express側の設定

expressの初期インストール

expressのサンプルを展開します

今回はreact-express-testというアプリ名にします

$ express react-express-test

  warning: the default view engine will not be jade in future releases
  warning: use `--view=jade' or `--help' for additional options


   create : react-express-test/
   create : react-express-test/public/
   create : react-express-test/public/javascripts/
   create : react-express-test/public/images/
   create : react-express-test/public/stylesheets/
   create : react-express-test/public/stylesheets/style.css
   create : react-express-test/routes/
   create : react-express-test/routes/index.js
   create : react-express-test/routes/users.js
   create : react-express-test/views/
   create : react-express-test/views/error.jade
   create : react-express-test/views/index.jade
   create : react-express-test/views/layout.jade
   create : react-express-test/app.js
   create : react-express-test/package.json
   create : react-express-test/bin/
   create : react-express-test/bin/www

   change directory:
     $ cd react-express-test

   install dependencies:
     $ npm install

   run the app:
     $ DEBUG=react-express-test:* npm start

サンプルができたら、モジュールをインストールします

$ cd react-express-test
$ npm install

npm WARN deprecated jade@1.11.0: Jade has been renamed to pug, please install the latest version of pug instead of jade
npm WARN deprecated constantinople@3.0.2: Please update to at least constantinople 3.1.1
npm WARN deprecated transformers@2.1.0: Deprecated, use jstransformer
npm notice created a lockfile as package-lock.json. You should commit this file.
added 101 packages from 150 contributors in 7.608s
expressの便利なパッケージのインストール

expressのデフォルトだと、エラーになった瞬間にストップするのでnodemonとインストールする

$ npm install nodemon

sevents@1.2.3 install /test-react/react-express-test/node_modules/fsevents
> node install

[fsevents] Success: "/test-react/react-express-test/node_modules/fsevents/lib/binding/Release/node-v57-darwin-x64/fse.node" already installed
Pass --update-binary to reinstall or --build-from-source to recompile

> nodemon@1.17.3 postinstall /test-react/react-express-test/node_modules/nodemon
> node -e "console.log('\u001b[32mLove nodemon? You can now support the project via the open collective:\u001b[22m\u001b[39m\n > \u001b[96m\u001b[1mhttps://opencollective.com/nodemon/donate\u001b[0m\n')" || exit 0

Love nodemon? You can now support the project via the open collective:
 > https://opencollective.com/nodemon/donate

+ nodemon@1.17.3
added 293 packages from 147 contributors in 18.056s

最終的にexpressとreactを同時に立ち上げないといけないので
並列?にコマンド発行できるconcurrentlyをインストールする

$ npm install concurrently
+ concurrently@3.5.1
added 15 packages from 11 contributors in 8.245s
express側のユーザーの取得プログラム

express側でユーザーを取得するダミーのプログラムを用意する
これは最終的にはmongodbとつなぐけどそこはあと・・・

expressはデフォルトでusersというrouterが設定されているので
そちらを修正する

$ cd /test-react/react-express-test/routes
$ vi users.js


下記の内容に変更する

var express = require('express');
var router = express.Router();

/* GET users listing. */
router.get('/', function(req, res, next) {
  res.json([{
  	id: 1,
  	username: "samsepi0l"
  }, {
  	id: 2,
  	username: "masalib"
  }]);
});

module.exports = router;
express側のportの変更する

portを指定しないとデフォルトの3000が起動する
herokuにあげる事も想定してportの指定をおこなう

$ cd /test-react/react-express-test/
$ vi app.js

app.jsの最後らへんに下記のような
「module.exports = app;」があるので
その上にportを指定する所を追加する

//
const port = process.env.PORT || 3001;
app.listen(port, () => console.log(`Server running on port ${port}`));

module.exports = app;
express側の起動コマンドを変更する

npm startでも確認はできるけど
エラーになった瞬間にとまるのでnodemon経由で起動するコマンドを追加する

cd /test-react/react-express-test/
vi package.json
  "scripts": {
    "start": "node ./bin/www",
    "server": "nodemon ./bin/www"
  },

確認コマンドは

$ cd /test-react/react-express-test/
$ npm run server

> react-express-test@0.0.0 server /test-react/react-express-test
> nodemon ./bin/www

[nodemon] 1.17.3
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node ./bin/www`
Server running on port 3001

poer 3001で立ち上がっている事が確認できた

react側

create-react-appしてプロジェクトの作成
$ cd /test-react/react-express-test/
$ create-react-app client

create-react-app client

Creating a new React app in /test-react/react-express-test/client.

Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts...


> fsevents@1.2.3 install /test-react/react-express-test/client/node_modules/fsevents
> node install

[fsevents] Success: "/test-react/react-express-test/client/node_modules/fsevents/lib/binding/Release/node-v57-darwin-x64/fse.node" already installed
Pass --update-binary to reinstall or --build-from-source to recompile

> uglifyjs-webpack-plugin@0.4.6 postinstall /test-react/react-express-test/client/node_modules/uglifyjs-webpack-plugin
> node lib/post_install.js

+ react-dom@16.3.2
+ react@16.3.2
+ react-scripts@1.1.4
added 1388 packages from 804 contributors in 61.885s

Success! Created client at /test-react/react-express-test/client
Inside that directory, you can run several commands:

  npm start
    Starts the development server.

  npm run build
    Bundles the app into static files for production.

  npm test
    Starts the test runner.

  npm run eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd client
  npm start

Happy hacking!

これでインストールができました

proxyの設定

作成したreactのプロジェクトのpackage.jsonを修正して
proxyの設定をしたいと思います

$ cd /test-react/react-express-test/client
$ vi package.json

下記のようにproxyの部分を追加する

  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "proxy": "http://localhost:3001"
usersのデータを取得するように修正する
$ cd /test-react/react-express-test/client/src/
$ vi App.js

下記のように修正する

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  state = {users: []}

  componentDidMount() {
    fetch('/users')
      .then(res => res.json())
      .then(users => this.setState({ users }));
  }

  render() {
    return (
      <div classname="App">
        <h1>Users</h1>
        {this.state.users.map(user =>
          <div key="{user.id}">{user.username}</div>
        )}
      </div>
    );
  }
}

export default App;

当たり前ですがnpm startをするとエラーになります

Compiled successfully!

You can now view client in the browser.

  Local:            http://localhost:3000/
  On Your Network:  http://192.168.10.104:3000/

Note that the development build is not optimized.
To create a production build, use npm run build.

Proxy error: Could not proxy request /users from localhost:3000 to http://localhost:3001.
See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNREFUSED).

expressとreactをつなぐ

expressとreactをつなぐために
同時に起動するコマンドを設定します

expressのフォルダからreactを起動する

修正前のpackage.json

  "scripts": {
    "start": "node ./bin/www"
    "server": "nodemon ./bin/www",
  },
cd /test-react/react-express-test/
vi package.json

修正後のpackage.json

  "scripts": {
    "start": "node ./bin/www",
    "server": "nodemon ./bin/www",
    "client": "PORT=3002 npm start --prefix client"

  },

prefixでclientのフォルダを相対的にさしています

確認コマンドは以下のとおりです

$ cd /test-react/react-express-test/
$ npm run client

この段階だとerrorになります

serverとclintを同時に起動する

www.npmjs.com

というパッケージで同時に起動させます

cd /test-react/react-express-test/
vi package.json

修正後のpackage.json

  "scripts": {
    "start": "node ./bin/www",
    "server": "nodemon ./bin/www",
    "client": "PORT=3002 npm start --prefix client",
    "dev": "concurrently \"npm run server\" \"npm run client\" "
  },

私の端末だと3000portは使われているよと怒られたので
Something is already running on port 3000. Probably:
portを3002にしています

確認コマンドは以下のとおりです

$ cd /test-react/react-express-test/
$ npm run dev 
> react-express-concurrently@0.0.1 dev /test-react/react-express-test
> concurrently "npm run server" "npm run client"

[0]
[0] > react-express-concurrently@0.0.1 server /test-react/react-express-test
[0] > nodemon ./bin/www --ignore './client/'
[0]
[1]
[1] > react-express-concurrently@0.0.1 client /test-react/react-express-test
[1] > PORT=3002 npm  start --prefix client
[1]
[1]
[1] > client@0.1.0 start /test-react/react-express-test/client
[1] > react-scripts start
[1]
[0] [nodemon] 1.17.3
[0] [nodemon] to restart at any time, enter `rs`
[0] [nodemon] watching: *.*
[0] [nodemon] starting `node ./bin/www`
[0] Server running on port 3001
[1] Starting the development server...
[1]
[1] Compiled successfully!
[1]
[1] You can now view client in the browser.
[1]
[1]   Local:            http://localhost:3002/
[1]   On Your Network:  http://192.168.10.104:3002/
[1]
[1] Note that the development build is not optimized.
[1] To create a production build, use npm run build.
[1]
[0] GET /users 304 22.093 ms - -

起動した結果はこんな感じです・・・
f:id:masalib:20180430020631j:plain

やっともとの開発に戻れる・・・
サンプルを理解していないで開発をやるとハマるな〜
理解するのにも時間がかかるな〜
いい方法はないものか