是否可以使用单个 package.json 在 Heroku 上托管 MERN 应用程序?
Is it possible to host MERN application on Heroku using single package.json?
我阅读了很多关于在 Heroku 上部署 MERN 应用程序的博客,但它们都使用单独的 package.json 客户端和服务器!
是否可以使用一个 package.json 文件?
My Project Structure
我的package.json
{
"name": "ecommerce",
"version": "0.1.0",
"private": true,
"author": "Dweep Panchal",
"license": "ISC",
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"braintree-web-drop-in-react": "^1.1.1",
"concurrently": "^5.2.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.1.2",
"react-scripts": "3.4.1",
"react-stripe-checkout": "^2.6.3",
"body-parser": "^1.19.0",
"braintree": "^2.22.0",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-jwt": "^5.3.3",
"express-validator": "^6.4.0",
"formidable": "^1.2.2",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.15",
"mongoose": "^5.9.7",
"stripe": "^8.46.0",
"uuid": "^7.0.3"
},
"scripts": {
"server": "cd ./backend && node app.js",
"start": "concurrently \"npm run server\" \"react-scripts start\"",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"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"
]
},
"proxy": "http://localhost:8000",
"devDependencies": {
"nodemon": "^2.0.3"
},
"engines": {
"node": "10.16.0",
"npm": "6.9.0"
}
}
app.js
require("dotenv").config({ path: "../.env" });
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const cors = require("cors");
const app = express();
// Routes
const authRoutes = require("./routes/auth");
const userRoutes = require("./routes/user");
const categoryRoutes = require("./routes/category");
const productRoutes = require("./routes/product");
const orderRoutes = require("./routes/order");
const stripeRoutes = require("./routes/stripepayment");
const braintreeRoutes = require("./routes/braintreepayment");
// DB Connection
mongoose
.connect(
`mongodb+srv://${process.env.DB_NAME}:${process.env.DB_PASS}@${process.env.DB_PROJECT}-xi8tq.mongodb.net/${process.env.DB_PROJECT}?retryWrites=true&w=majority`,
{
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
useFindAndModify: true,
}
)
.then(() => console.log("DB Connected!"))
.catch(() => console.log("Failed to Connect DB"));
// Middleware
app.use(bodyParser.json());
app.use(cookieParser());
app.use(cors());
// My Routes
app.use("/api", authRoutes);
app.use("/api", userRoutes);
app.use("/api", categoryRoutes);
app.use("/api", productRoutes);
app.use("/api", orderRoutes);
app.use("/api", stripeRoutes);
app.use("/api", braintreeRoutes);
// Server Connection
const port = process.env.BACKEND_PORT || 8000;
app.listen(port, () => console.log(`Server Running at Port ${port}`));
当我在 heroku 上部署此应用程序时,项目 url 显示:
无效主机header
是的,如果您的后端服务于您的前端,这是可能的。当您的后端和前端 运行 在两个单独的节点程序上时,两个 package.json
很有用。
invalid host headers
可能是由于您的服务器处理 headers 的方式所致,但由于您没有发布 minimal reproducible example,目前我们无法进一步帮助您。
让我快速解释一下部署任何 Reactjs 和 express 到 heroku 是如何工作的。目标是使用 npm 运行 build 生成一个构建文件夹,然后启动服务器以提供该构建文件夹中的静态内容。
在 heroku 文档中,它指出 heroku-postbuild 运行s 在启动脚本之前。这是执行 npm 运行 build 以生成构建文件夹然后使用启动脚本 运行 您的服务器代码的理想场所。从那里您的服务器应该使用 express.static 并指向您生成构建文件夹的位置。
这就是人们喜欢使用服务器的原因 package.json 因为它不会干扰反应启动脚本。现在我立即看到的问题是您没有正确使用脚本,也没有指向您应该生成的构建文件夹。
在您的 package.json 中创建一个启动脚本来启动您的 app.js 文件,然后创建一个将生成构建文件夹的 heroku-postbuild。喜欢下面
"scripts": {
"start": "cd ./backend && node app.js",
"heroku-postbuild": "npm run build",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
之后你的 app.js 中应该有 app.use(express.static(<<location of build folder>>))
。在您的 app.js
中添加以下代码
if (process.env.NODE_ENV === "production") {
app.use(express.static("../build"));
}
我说 ../build 的原因是因为您的构建文件夹在后端文件夹之外。
我还检查了你的整个代码,还有其他小的配置问题。例如,如果你部署到 heroku ,你应该使用 process.env.PORT
我阅读了很多关于在 Heroku 上部署 MERN 应用程序的博客,但它们都使用单独的 package.json 客户端和服务器!
是否可以使用一个 package.json 文件?
My Project Structure
我的package.json
{
"name": "ecommerce",
"version": "0.1.0",
"private": true,
"author": "Dweep Panchal",
"license": "ISC",
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"braintree-web-drop-in-react": "^1.1.1",
"concurrently": "^5.2.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.1.2",
"react-scripts": "3.4.1",
"react-stripe-checkout": "^2.6.3",
"body-parser": "^1.19.0",
"braintree": "^2.22.0",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-jwt": "^5.3.3",
"express-validator": "^6.4.0",
"formidable": "^1.2.2",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.15",
"mongoose": "^5.9.7",
"stripe": "^8.46.0",
"uuid": "^7.0.3"
},
"scripts": {
"server": "cd ./backend && node app.js",
"start": "concurrently \"npm run server\" \"react-scripts start\"",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"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"
]
},
"proxy": "http://localhost:8000",
"devDependencies": {
"nodemon": "^2.0.3"
},
"engines": {
"node": "10.16.0",
"npm": "6.9.0"
}
}
app.js
require("dotenv").config({ path: "../.env" });
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const cors = require("cors");
const app = express();
// Routes
const authRoutes = require("./routes/auth");
const userRoutes = require("./routes/user");
const categoryRoutes = require("./routes/category");
const productRoutes = require("./routes/product");
const orderRoutes = require("./routes/order");
const stripeRoutes = require("./routes/stripepayment");
const braintreeRoutes = require("./routes/braintreepayment");
// DB Connection
mongoose
.connect(
`mongodb+srv://${process.env.DB_NAME}:${process.env.DB_PASS}@${process.env.DB_PROJECT}-xi8tq.mongodb.net/${process.env.DB_PROJECT}?retryWrites=true&w=majority`,
{
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
useFindAndModify: true,
}
)
.then(() => console.log("DB Connected!"))
.catch(() => console.log("Failed to Connect DB"));
// Middleware
app.use(bodyParser.json());
app.use(cookieParser());
app.use(cors());
// My Routes
app.use("/api", authRoutes);
app.use("/api", userRoutes);
app.use("/api", categoryRoutes);
app.use("/api", productRoutes);
app.use("/api", orderRoutes);
app.use("/api", stripeRoutes);
app.use("/api", braintreeRoutes);
// Server Connection
const port = process.env.BACKEND_PORT || 8000;
app.listen(port, () => console.log(`Server Running at Port ${port}`));
当我在 heroku 上部署此应用程序时,项目 url 显示:
无效主机header
是的,如果您的后端服务于您的前端,这是可能的。当您的后端和前端 运行 在两个单独的节点程序上时,两个 package.json
很有用。
invalid host headers
可能是由于您的服务器处理 headers 的方式所致,但由于您没有发布 minimal reproducible example,目前我们无法进一步帮助您。
让我快速解释一下部署任何 Reactjs 和 express 到 heroku 是如何工作的。目标是使用 npm 运行 build 生成一个构建文件夹,然后启动服务器以提供该构建文件夹中的静态内容。
在 heroku 文档中,它指出 heroku-postbuild 运行s 在启动脚本之前。这是执行 npm 运行 build 以生成构建文件夹然后使用启动脚本 运行 您的服务器代码的理想场所。从那里您的服务器应该使用 express.static 并指向您生成构建文件夹的位置。
这就是人们喜欢使用服务器的原因 package.json 因为它不会干扰反应启动脚本。现在我立即看到的问题是您没有正确使用脚本,也没有指向您应该生成的构建文件夹。
在您的 package.json 中创建一个启动脚本来启动您的 app.js 文件,然后创建一个将生成构建文件夹的 heroku-postbuild。喜欢下面
"scripts": {
"start": "cd ./backend && node app.js",
"heroku-postbuild": "npm run build",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
之后你的 app.js 中应该有 app.use(express.static(<<location of build folder>>))
。在您的 app.js
if (process.env.NODE_ENV === "production") {
app.use(express.static("../build"));
}
我说 ../build 的原因是因为您的构建文件夹在后端文件夹之外。
我还检查了你的整个代码,还有其他小的配置问题。例如,如果你部署到 heroku ,你应该使用 process.env.PORT