如何使用后端文件夹内的前端将 MERN 应用程序部署到 Heroku
Posted
技术标签:
【中文标题】如何使用后端文件夹内的前端将 MERN 应用程序部署到 Heroku【英文标题】:How to deploy MERN app to Heroku with frontend inside of backend folder 【发布时间】:2021-11-12 14:39:12 【问题描述】:将我的 MERN 应用程序部署到 heroku 表示构建已成功,但在打开应用程序时,它显示的只是未找到。我怀疑路由和路径存在问题,尤其是在后端的 index.js 中。如标题所述,前端位于后端文件夹内,因此两者只能使用一个网站。我已遵循 this GitHub repo 的所有建议来执行此过程。我在包含代码方面做得太过火了,因为我不知道问题出在哪里,而且正如您在生产中所知道的那样,这一切都是相互关联的。据我了解,在 heroku-postbuild 之前,我不需要运行 React 的构建/生产文件夹,但 heroku 找不到构建文件夹或其 index.html。
项目结构
api //frontend is inside backend for the benefit of only deploying to one site
-mappinapp //the react frontend
----node_modules
----public
------index.html
----src
------components
------App.js
------config.js
------index.js
----.env
----.gitignore
----package-lock.json
----package.json
-models
-node_modules
-routes
-.env
-.gitignore
-index.js
-package-lock.json
-package.json
Heroku 日志 --tail
heroku[router]: at=info method=GET path="/" host=mappinapp.herokuapp.com request_id=redacted fwd="redacted" dyno=web.1 connect=0ms service=9ms status=404 bytes=380 protocol=https
app[web.1]: Error: ENOENT: no such file or directory, stat '/app/mappinapp/build/index.html'
api(后端) package.json
"name": "api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts":
"start": "node index.js",
"heroku-postbuild": "cd mappinapp && npm install && npm run build" //build succeeded on heroku
,
"keywords": [],
"author": "",
"license": "ISC",
"dependencies":
"bcrypt": "^5.0.1",
"dotenv": "^8.6.0",
"express": "^4.17.1",
"mongoose": "^5.13.9",
"nodemon": "^2.0.7",
"path": "^0.12.7"
api(后端)的index.js
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const userRoute = require("./routes/users");
const pinRoute = require("./routes/pins");
const path = require("path");
dotenv.config();
app.use(express.json());
mongoose
.connect(process.env.MONGO_URL,
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true, )
.then(() => console.log("MongoDB connected!"))
.catch(err => console.log(err));
app.use("/api/users", userRoute);
app.use("/api/pins", pinRoute);
// app.use(express.static(path.join(__dirname, "/api/mappinapp/build")));
app.get('*', function (req, res)
const index = path.join(__dirname, '/mappinapp/build', 'index.html');
console.log(__dirname);
res.sendFile(index);
);
app.listen(process.env.PORT || 5000, () =>
console.log("Backend server is running!");
);
在阅读this post后注释掉了app.use行并添加了app.get函数 我确实注意到将鼠标悬停在“/api/mappinapp/build”或“/mappinapp/build”上并不会像“./routes/users”那样显示路径。我已经尝试以多种方式更改路径并使用 app.use(express... 行。我怀疑这是问题所在,但可能不是。
config.js
import axios from "axios";
export const axiosInstance = axios.create(
baseURL: "https://mappinapp.herokuapp.com/api/"
)
api(后端) .gitignore
/node_modules
.env
前端.gitignore
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production - removed /build in case having it in the .gitignore would cause issues.
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
在 heroku 上打开应用显示 NOT FOUND,控制台显示
Content Security Policy: The page’s settings blocked the loading of a resource at inline (“default-src”). moz-extension:1592:49
Content Security Policy: The page’s settings blocked the loading of a resource at https://mappinapp.herokuapp.com/favicon.ico (“default-src”). resource:191:19
Content Security Policy: The page’s settings blocked the loading of a resource at inline (“default-src”). moz-extension:199:11
不确定是否相关,但我包括在内
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'self';" />
在前端 react 应用的 index.html 中。在浏览器控制台日志中仍然显示相同的错误。
最后,
heroku 构建日志
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Using buildpack: heroku/nodejs
remote: -----> Node.js app detected
remote:
remote: -----> Creating runtime environment
remote:
remote: NPM_CONFIG_LOGLEVEL=error
remote: NODE_VERBOSE=false
remote: NODE_ENV=production
remote: NODE_MODULES_CACHE=true
remote:
remote: -----> Installing binaries
remote: engines.node (package.json): unspecified
remote: engines.npm (package.json): unspecified (use default)
remote:
remote: Resolving node version 14.x...
remote: Downloading and installing node 14.17.6...
remote: Using default npm version: 6.14.15
remote:
remote: -----> Restoring cache
remote: - node_modules
remote:
remote: -----> Installing dependencies
remote: Installing node modules
remote:
remote: > bcrypt@5.0.1 install /tmp/build_4d6aebd0/node_modules/bcrypt
remote: > node-pre-gyp install --fallback-to-build
remote:
remote: [bcrypt] Success: "/tmp/build_4d6aebd0/node_modules/bcrypt/lib/binding/napi-v3/bcrypt_lib.node" is installed via remote
remote:
remote: > nodemon@2.0.12 postinstall /tmp/build_4d6aebd0/node_modules/nodemon
remote: > node bin/postinstall || exit 0
remote:
remote: Love nodemon? You can now support the project via the open collective:
remote: > https://opencollective.com/nodemon/donate
remote:
remote: added 248 packages in 5.263s
remote:
remote: -----> Build
remote: Running heroku-postbuild
remote:
remote: > api@1.0.0 heroku-postbuild /tmp/build_4d6aebd0
remote: > cd mappinapp && npm install && npm run build
remote:
remote: audited 248 packages in 2.297s
remote:
remote: 15 packages are looking for funding
remote: run `npm fund` for details
remote:
remote: found 0 vulnerabilities
remote:
remote:
remote: -----> Caching build
remote: - node_modules
remote:
remote: -----> Pruning devDependencies
remote: audited 248 packages in 2.168s
remote:
remote: 15 packages are looking for funding
remote: run `npm fund` for details
remote:
remote: found 0 vulnerabilities
remote:
remote:
remote: -----> Build succeeded!
remote: -----> Discovering process types
remote: Procfile declares types -> (none)
remote: Default types for buildpack -> web
remote:
remote: -----> Compressing...
remote: Done: 35.8M
remote: -----> Launching...
remote: Released v16
remote: https://mappinapp.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
【问题讨论】:
【参考方案1】:就在server.js
中的app.listen()
上方,我通常在部署Heroku时添加以下内容:
if (process.env.NODE_ENV === 'production')
app.use(express.static(path.join(__dirname, 'mappinapp', 'build')));
app.get('*', (req, res) =>
res.sendFile(path.resolve(__dirname, 'mappinapp', 'build', 'index.html'));
);
在根目录中创建Procfile
:
web: npm install
web: npm start
并确保此脚本位于package.json
:
"scripts":
"start": "node server",
"server": "nodemon server",
"client": "npm run start --prefix mappinapp",
"heroku-postbuild": "npm install --prefix client && npm run build --prefix client"
【讨论】:
没有任何理由将npm install
作为web
进程运行。 javascript buildpack 应该在部署过程中安装您的依赖项。以上是关于如何使用后端文件夹内的前端将 MERN 应用程序部署到 Heroku的主要内容,如果未能解决你的问题,请参考以下文章