我正在尝试部署react + Express应用程序,但是本地npm start
不会获取client
文件夹中的react build。
我已经完成了一个反应构建,因此客户端文件夹中确实存在一个 build文件夹。
文件夹结构
完整的文件夹结构
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"
]
}
}
答案 0 :(得分:1)
您似乎正在尝试在代码中的几个不同位置公开构建文件夹。
您应该删除app.use(express.static(path.join(__dirname, 'build')));
,因为该路径无效。在main.js
的更深处,您正在执行正确的路径,但是如果代码块已废弃,则生产可能会再次弄乱路径。因此,您也可以删除它。
也可以翻译
//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'));
})
对此
//build mode
app.use(express.static(path.join(__dirname, 'client/build')));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '/client/public/index.html'));
})