4

I'm working on a pretty simple App (my first), but I can't figure out how to get both the API and the react server to start...

I'm using for client routes and I've used on another project so I've started my React project with it to setup the API.

But I was wondering if there was a way to use to handle API routes and return some data...

I've googled and looked around but I can seem to find anything about that (nor confirming nor refuting).

Does anyone have any input about that?
(I know it isn't a proper SO question but I can't seem to find any info to close the nagging wonder)

2 Answers 2

1

I'm working on a pretty simple react App (my first), but I can't figure out how to get both the API and the react server to start...

There is an npm module that I use for my React/Express app called concurrently that I use to start my client and backend servers at the same time.

I installed that globally:

npm install concurrently

In my app's main package.json, I have the scripts setup like this:

"scripts":{
  "start": "concurrently \"npm run server\" \"npm run client\"",
  "server": "node bin/www",
  "client": "node start-client.js"
}

That setup allows me to run npm start and it starts up my server and client scripts.

In start-client.js, I have this:

const args = ["start"];
const opts = { stdio: "inherit", cwd: "client", shell: true };
require("child_process").spawn("npm", args, opts);

start-client.js is located at the root of my app.

My file structure looks like this:

|--bin
|--client
|--routes
|--app.js
|--package.json
|--start-client.js

But I was wondering if there was a way to use react-router to handle API routes and return some data...

To fetch data from the API server, I use the native fetch() method inside my React components.

Since I'm using Express, I will create a route and export it to my app.js file like so:

/* myRoute.js */
var express = require('express')
var router = express.Router()

router.get('/', function(req, res, next) {
  res.send('index', {title: 'Express'})
})

module.exports = router

/* app.js */

var myRoute = require('./routes/myRoute')
var app = express()
//will fetch data from this endpoint
app.use('/myRoute', myRoute)

Now in my React component, I will fetch data from /myRoute like so:

fetch('/myRoute')
  .then(res => JSON.parse(res))
  .then(res => console.log(res))
Sign up to request clarification or add additional context in comments.

3 Comments

Thx for the input, I've almost understand everything, but one thing still any me : I guess myRoute.js is in ./routes/, but what do you have in ./bin/ and ./bin/www/? And to be sure, does concurrently also works in production?
And what about build scripts can we use concurrently too?
@R3uK bin/www starts up my node server. You probably call it server.js. I haven't used concurrently in production yet, but I don't see why it shouldn't work in production. You can read more about it here: npmjs.com/package/concurrently
1

There's a way to start both API server and react. In your express main file in my case server.js. You'd need to install webpack-dev-middleware and webpack-hot-middleware.

// server.js
import path from 'path';
import express from 'express';
import webpack from 'webpack';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import config from './webpack.config';

const app = express(),
  DIST_DIR = path.join(__dirname, 'client'),
  HTML_FILE = path.join(DIST_DIR, 'index.html'),
  compiler = webpack(config),
  isDevelopment = process.env.NODE_ENV === 'development';

if (isDevelopment) {
  app.use(webpackDevMiddleware(compiler, {
    publicPath: config.output.publicPath,
  }));

  app.use(webpackHotMiddleware(compiler));
} else {
  app.use(express.static(DIST_DIR));
}

app.get('/', (req, res) => res.sendFile(HTML_FILE));
app.get('*', (req, res) => res.redirect(301, '/'));

app.listen(process.env.PORT || 4200);

Then in your webpack.config.js, you can follow my settings below:

const path = require('path');
const webpack = require('webpack');

process.env.NODE_ENV = process.env.NODE_ENV || 'development';

module.exports = {
  entry: [
    'webpack-hot-middleware/client',
    './app/app.jsx',
  ],
  externals: {
    jquery: 'jQuery',
    'react/addons': 'react',
    'react/lib/ExecutionEnvironment': 'react',
    'react/lib/ReactContext': 'react',
  },
  output: {
    path: path.resolve(__dirname, 'client'),
    filename: 'bundle.js',
    publicPath: '/',
    sourceMapFilename: 'bundle.map',
  },
  devtool: process.env.NODE_ENV === 'production'
    ? undefined : 'cheap-module-eval-source-map',
  resolve: {
    modules: ['node_modules', './app/components'],
    extensions: ['.js', '.jsx'],
  },
  module: {
    rules: [
      {
        test: /(\.js$|\.jsx$)/,
        exclude: /(node_modules|bower_components)/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: ['react', 'es2015', 'stage-0', 'airbnb'],
            },
          },
        ],
      },
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader'],
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[name].[ext]'
          }
        }
      }
    ],
  },
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
    }),
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: true,
      minimize: true,
      compressor: {
        warnings: false,
      },
    }),
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify(process.env.NODE_ENV)
      },
    }),
  ],
};

Then in your package.json scripts:

// package.json
"scripts": {
    "build": "webpack",
    "postinstall": "npm run build",
    "start": "babel-node server.js",
    "start:dev": "nodemon -e js --exec babel-node -- ./server.js",
    "test": "karma start"
  }

Now when you start your express server, your API and react will run together.

2 Comments

Thx for the input, that seems to handle both dev and prod start methods! But about build script does it work too? What do I have to define in package.json's scripts? Thx in advance for the explanations!
I've added it to the bottom of the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.