Reputation: 1362
I'm trying to deploy a react + express app, but locally npm start
does not fetch the react build that is within the client
folder.
I have already done a react build, so a build folder does exist within the client folder.
folder structure
full folder structure
main.js
import 'dotenv/config';
import cors from 'cors';
import express from 'express';
import logger from 'morgan';
import path from 'path';
import bodyParser from 'body-parser';
import cookieParser from 'cookie-parser';
import userRoute from './routes/users';
import imageRoute from './routes/images';
import passport from 'passport';
import session from 'express-session';
import './config/passport';
import knex from 'knex';
import config from './knexfile'
import KnexSessionStore from 'connect-session-knex';
const knexSession = KnexSessionStore(session);
const myKnex = knex(config.development);
const store = new knexSession({
knex:myKnex,
// tablename:'sessions'
})
const app = express();
app.use(cors({
origin:process.env.ALLOW_ORIGIN,
preflightContinue: false,
credentials: true,
allowedHeaders: 'X-Requested-With, Content-Type, Authorization',
methods: 'GET, POST, PATCH, PUT, POST, DELETE, OPTIONS',
exposedHeaders: ['Content-Length', 'X-Foo', 'X-Bar'],
}))
app.use(logger('dev'));
// For React Stuff if need be
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'build')));
app.use(cookieParser());
app.use(bodyParser.json());
// you need body parser urlencoded so passport will not give a Missing Credentials error
app.use(session({
store: store,
saveUninitialized: false,
resave:false,
cookie: { maxAge: 30 * 24 * 60 * 60 * 1000 }, // 30 days
secret : process.env.JWT_SECRET,
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(bodyParser.urlencoded({ extended:false}));
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.use('/users', userRoute);
app.use('/images', imageRoute);
// app.use('/images', imageRoute);
// app.use('/comments', imageRoute);
app.use(() => (req, res, next) =>{
res.locals.user = req.user; // This is the important line
// req.session.user = user
console.log(res.locals.user);
next();
});
app.use('/', function (req, res, next) {
var n = req.session.views || 0
req.session.views = ++n
res.end(n + ' views')
console.log(n);
})
//build mode
app.use(express.static(path.join(__dirname, 'client/build')));
// if(process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, 'client/build')));
//
app.get('*', (req, res) => {
res.sendfile(path.join(__dirname = 'client/build/index.html'));
})
// }
//build mode
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname+'/client/public/index.html'));
})
// module.parent prevents the
// Node / Express: EADDRINUSE, Address already in use error when unit testing
if(!module.parent){
app.listen(process.env.PORT, () =>
console.log(`Example app listening on port ${process.env.PORT}!`),
);
}
export default app;
package.json
{
"name": "somethingapp",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"client-install": "npm install --prefix client",
"test": "./node_modules/.bin/mocha --watch --require @babel/register",
"server": "nodemon --exec babel-node main.js",
"client": "cd ./client && npm start ",
"start": "babel-node main.js",
"startdev": "concurrently --kill-others \"npm run client\" \"npm run server\" ",
"migrate": "babel-node node_modules/.bin/knex migrate:latest",
"rollback": "babel-node node_modules/.bin/knex migrate:rollback ",
"seed": "babel-node node_modules/.bin/knex seed:run",
"heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix client && npm run build --prefix client",
"build": "concurrently \"cd client && npm run build\" \"npm build \""
},
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^3.0.6",
"body-parser": "^1.19.0",
"bookshelf": "^0.14.2",
"bookshelf-validate": "^2.0.3",
"chai-http": "^4.3.0",
"cloudinary": "^1.14.0",
"concurrently": "^4.1.0",
"connect-multiparty": "^2.2.0",
"connect-session-knex": "^1.4.0",
"cookie-parser": "^1.4.4",
"cors": "^2.8.5",
"dotenv": "^8.0.0",
"dump-die": "^1.0.0",
"express": "^4.17.0",
"express-session": "^1.16.1",
"express-validator": "^5.3.1",
"jsonwebtoken": "^8.5.1",
"knex": "^0.16.5",
"morgan": "^1.9.1",
"multer": "^1.4.1",
"multiparty": "^4.2.1",
"passport": "^0.4.0",
"passport-github": "^1.1.0",
"passport-google-oauth": "^2.0.0",
"passport-google-oauth20": "^2.0.0",
"passport-jwt": "^4.0.0",
"passport-local": "^1.0.0",
"path": "^0.12.7",
"pg": "^7.11.0",
"validator": "^11.0.0",
"var_dump": "^1.0.5"
},
"devDependencies": {
"@babel/cli": "^7.4.4",
"@babel/core": "^7.4.5",
"@babel/node": "^7.4.5",
"@babel/preset-env": "^7.4.5",
"@babel/register": "^7.4.4",
"chai": "^4.2.0",
"mocha": "^6.1.4",
"nodemon": "^1.19.0",
"reify": "^0.19.1",
"request": "^2.88.0"
}
}
client/package.json
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"@material-ui/core": "^4.0.1",
"axios": "^0.18.0",
"jsonwebtoken": "^8.5.1",
"jwt-decode": "^2.2.0",
"moment": "^2.24.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-github-login": "^1.0.3",
"react-google-login": "^5.0.4",
"react-images-upload": "^1.2.6",
"react-redux": "^7.0.3",
"react-router-dom": "^5.0.0",
"react-scripts": "3.0.1",
"react-social-login-buttons": "^2.3.1",
"react-thunk": "^1.0.0",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0"
},
"scripts": {
"start": "PORT=3001 react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"heroku-postbuild": "npm run build"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
"enzyme-to-json": "^3.3.5",
"redux-devtools-extension": "^2.13.8",
"redux-mock-store": "^1.5.3"
},
"jest": {
"snapshotSerializers": [
"enzyme-to-json/serializer"
]
}
}
Upvotes: 2
Views: 1131
Reputation: 25842
It looks like you are trying to expose the build folder in a few different places in the code.
You should drop app.use(express.static(path.join(__dirname, 'build')));
as that path is invalid. Further down inside main.js
you are doing the correct path, but your production if block is obsolete and can potentially mess up the paths again. So you can remove that as well.
Aka translate this
//build mode
app.use(express.static(path.join(__dirname, 'client/build')));
// if(process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, 'client/build')));
//
app.get('*', (req, res) => {
res.sendfile(path.join(__dirname = 'client/build/index.html'));
})
// }
//build mode
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname+'/client/public/index.html'));
})
to this
//build mode
app.use(express.static(path.join(__dirname, 'client/build')));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '/client/public/index.html'));
})
Upvotes: 2