Reputation: 14537
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...
I'm using react-router for client routes and I've used express 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 react-router 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)
Upvotes: 4
Views: 1017
Reputation: 10864
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.
Upvotes: 1
Reputation: 3332
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))
Upvotes: 1