node.js - Mongodb、Reactjs、Express、Node js Heroku 部署显示空白页和 404 错误。在本地工作
问题描述
我的应用程序在本地运行。路线通过邮递员工作,并且 DB 被击中(如 Robo 3t 所示)。Heroku 部署构建只是为了在应用程序启动时显示一个空白页面。控制台显示如下: 在此处输入图像描述
下面是我的代码:
服务器.js
const express = require("express");
const app = express();
const path = require("path");
const mongoose = require("mongoose");
const routes = require("./routes");
const bodyParser = require("body-parser");
const cors = require ('cors');
require('dotenv').config()
const PORT = process.env.PORT || 3001;
// Connect to the Mongo DB
mongoose.connect(
process.env.MONGODB_URI || "mongodb://localhost/sfwReactPortfolio",
{
useNewUrlParser: true,
useUnifiedTopology: true,
// useCreateIndex: true,
useFindAndModify: false
}
);
mongoose.set('useCreateIndex', true);
// mongoose.createConnection(
// process.env.MONGODB_URI || "mongodb://localhost/sfwReactPortfolio",
// {
// useUnifiedTopology: true,
// useNewUrlParser: true,
// useFindAndModify: false,
// });
// /** */ const Book = mongoConnection.model('Book', bookSchema /*, 'COLLECTION_NAME'*/);
const mongoose_db = mongoose.connection;
// Define middlewares here for parsing req.body:
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(cors());
// Configure body parsing for AJAX requests
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
// Serve up static assets
if (process.env.NODE_ENV === "production") {
app.use(express.static("client/build"));
}
// Currently serving static assets
app.use(express.static(path.join(__dirname, "public")));
// Add routes, both API and view
app.use(routes);
// // Verifies connection to db on desired port.
mongoose_db.once("open", function() {
app.listen(PORT, () => {console.log("Server Listening on Port", PORT)});
})
// // Throws error on failed db connection check.
mongoose_db.on("error", function() {
console.error("database failed to open");
})
路线 - index.js
const express = require("express");
const router = express.Router();
const nodemailer = require("nodemailer")
const ContactForm = require('../models/contactForm');
router.post("/api/messages", (req,res)=>{
let data = req.body
let smtpTransport = nodemailer.createTransport({
service:"Gmail",
port:465,
auth: {
user:"sfwportfoliomessages@gmail.com",
pass: "git4tm3!"
}
});
let mailOptions = {
from: data.email,
to:"sfwportfoliomessages@gmail.com",
subject: `Message from ${data.firstName}`,
html:`
<h3>Information</h3>
<ul>
<li>firstName: ${data.firstName}</li>
<li>lastName: ${data.lastName}</li>
<li>email: ${data.email}</li>
</ul>
<h3>Message</h3>
<p>${data.message}</p>
<p>${data.time}</p>
`
};
smtpTransport.sendMail(mailOptions, (error, res)=>{
if(error) {
res.send(error)
} else {
res.send("Success")
}
})
smtpTransport.close();
ContactForm.create(req.body,
function (err, response) {
console.log(`response: ${response}`)
if (err){
console.log(err)
return
}
res.json(response)
}
)
})
module.exports = router;
模型架构
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const ContactSchema = new Schema ({
firstName: {type: Schema.Types.String},
lastName: {type: Schema.Types.String},
email: {type: Schema.Types.String},
message: {type: Schema.Types.String},
pubDate: {
type: Schema.Types.Date,
default: Date.now,
},
})
const ContactFrom = mongoose.model("ContactForm", ContactSchema);
module.exports = ContactFrom;
前端 App.js
import React from 'react';
import {BrowserRouter as Router, Switch, Route} from "react-router-dom"
import Header from "../src/components/header"
import Footer from "../src/components/footer"
import Portfolio from "../src/pages/portfolio"
import About from "../src/pages/about"
import Contact from "../src/pages/contact"
function App() {
return (
<div className="App container-fluid container-sm">
<Router>
<Header/>
<Switch>
<Route exact path={["/about","/", "/hw-unit20-reactPortfolio"]}>
<About />
</Route>
<Route path="/contact">
<Contact />
</Route>
<Route exact path="/portfolio">
<Portfolio />
</Route>
</Switch>
</Router>
<Footer/>
</div>
);
}
export default App;
清单.json
{
"short_name": "React App",
"name": "Create React App Sample",
"start_url": "./index.html",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
后端包.json
{
"name": "hw-unit20-reactPortfolio",
"version": "1.0.0",
"engines": {
"node": "12.x"
},
"description": "portfolio v4 created with REACT",
"main": "server.js",
"dependencies": {
"body-parser": "^1.19.0",
"concurrently": "^5.2.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"if-env": "^1.0.4",
"moment": "^2.27.0",
"mongodb": "^3.5.9",
"mongoose": "^5.9.19",
"nodemailer": "^6.4.10",
"nodemon": "^2.0.4",
"path": "^0.12.7",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0"
},
"devDependencies": {},
"scripts": {
"start": "if-env NODE_ENV=production && npm run start:prod || npm run start:dev",
"start:prod": "node server.js",
"start:dev": "concurrently \"nodemon --ignore 'client/*'\" \"npm run client\"",
"client": "cd client && npm run start",
"install": "cd client && npm install",
"build": "cd client && npm run build",
"heroku-postbuild": "npm run build"
}
}
客户端包.json
{
"name": "app",
"homepage": "https://SpencerFalor-Ward.github.io/hw-unit20-reactPortfolio",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:3001/",
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"axios": "^0.19.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"predeploy": "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"
]
}
}
索引.html
<!DOCTYPE html>
<html lang="en-us">
<!--Header containg site tab title, character set, link to CSS sheet-->
<head>
<meta charset="UTF-8">
<!-- <link rel="stylesheet" type="text/css" href="../src/assets/css/reset.css"> -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" type="text/css" src="./assets/css/styles.css">
<title>SFW Digital Buisiness Card</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
文件结构 在此处输入图像描述
我很感激这里的任何帮助!
解决方案
我找到了答案!使用本指南https://coursework.vschool.io/deploying-mern-with-heroku/引导我将以下代码行添加到我的 server.js 中:
app.use(express.static(path.join(__dirname, "client", "build")))
在我已经存在的范围内
if (process.env.NODE_ENV === "production") {
app.use("<git repo name>", express.static("client/build"));
}
我添加了
app.get("*", (req, res) => {
res.sendfile(path.resolve(__dirname, "client", "build", "index.html"));
})
我还确保将上面的“if.....”代码放在包含我的“app.listen ....”的代码之前
我的仓库在这里:https ://github.com/SpencerFalor-Ward/hw-unit20-reactPortfolio
虽然我之前在没有这里使用的代码的情况下成功地将 MERN 应用程序部署到 Heroku,但这次是需要的。
推荐阅读
- java - 使用 instanceof 扩展 java.util.Date 的掩码对象返回 true
- python - 类型错误:需要整数参数
- reactjs - 堆栈中嵌套抽屉时不显示屏幕标题
- sqlite - 使用 Xamarin.Forms 从 Sqlite 数据库中获取数据
- asp.net - 如何使用 ASP.NET 在解决方案中存储图像?
- php - 在 Woocommerce 中发送特定运输方式的订单保留电子邮件
- java - 是否可以将 LibGDX 与 MoltenGL 一起使用
- css - 边距样式在 Angular 和 Bootstrap 中不起作用
- video - 获取生成缩略图的第二个
- angular - templateUrl 按角度 4 中的类动态