在 Heroku 上部署 React 应用和 API 的最佳实践
Posted
技术标签:
【中文标题】在 Heroku 上部署 React 应用和 API 的最佳实践【英文标题】:Best practices to deploy a React app and an API on Heroku 【发布时间】:2020-10-26 07:01:57 【问题描述】:我目前正在开发一个使用 React(通过 create-react-app
)和 JSONServer 作为 API 的项目。
我有一个单一的 Git 存储库,结构如下:
|-- client
|-- api
为了在开发环境中工作,我以 npm start
开头两个文件夹,以便为 React 应用程序提供 http://localhost:3000,为 API 提供 http://localhost:3001。
这样(感谢 Axios)我可以连接到 http://localhost:3001/api 来检索我的内容
import axios from 'axios'
export default axios.create(
baseURL: 'http://localhost:3001/api'
)
到目前为止一切都很好。
现在我想将我的应用和 API 部署到 Heroku,这就是事情变得复杂的地方。
所以这是我的问题,如果您能就处理问题的最佳方法提供一些建议,将会非常有帮助:
我应该在 Heroku 上创建两个应用程序吗?一个用于客户端,一个用于 API? 如果我在 Heroku 上有两个应用程序,如何从客户端安全地访问 API?可能会获取 API 应用程序的 url(如 https://myapp.herokuapp.com/api),但我必须处理 CORS 问题。 或者我应该只使用 API 创建一个应用程序并将客户端的构建放在同一个文件夹/url (例如:使用 JSONServer 提供构建的公共文件)目前,我在客户端文件夹的根目录中有一个 server.js
文件和一个带有 web: node server.js
的 Procfile
来启动构建服务器。然后我使用 Axios 从另一个 Heroku 应用程序(实际上是 API 应用程序)获取数据。
任何建议/帮助将不胜感激!谢谢!
P.S.:这是我的 package.json 和 server.js 文件,用于客户端和 api
客户端的 server.js(位于客户端文件夹的根目录)
const express = require('express')
const http = require('http')
const path = require('path')
const app = express()
app.use(express.static(path.join(__dirname, 'build')))
const port = process.env.PORT || '8080'
app.set('port', port)
const server = http.createServer(app)
server.listen(port, () => console.log(`Running on localhost:$port`))
Api 的 server.js(位于 api 文件夹的根目录)
const express = require('express');
const jsonServer = require('json-server');
const router = express.Router();
const server = jsonServer.create();
const mainRoute = jsonServer.router('db.json');
const middlewares = jsonServer.defaults( noCors: false );
const port = process.env.PORT || 3001;
router.use('/api', mainRoute)
server.use(middlewares);
server.use(router);
server.listen(port);
客户的 package.json:
"name": "portfolio",
"version": "0.1.0",
"private": true,
"dependencies":
"@emotion/core": "^10.0.28",
"@emotion/styled": "^10.0.27",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"axios": "^0.19.2",
"express": "^4.17.1",
"google-spreadsheet": "^3.0.11",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-intl": "^4.6.3",
"react-lazyload": "^2.6.8",
"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",
"postinstall": "react-scripts build"
,
"proxy": "https://my-api.herokuapp.com/api",
"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":
"eslint-plugin-react": "^7.20.0",
"react-spring": "^8.0.27",
"standard": "^14.3.4"
Api 的 package.json:
"name": "json-server-heroku",
"version": "1.0.0",
"description": "Simple json-base database to deploy to Heroku",
"main": "server.js",
"scripts":
"start": "node server.js",
"dev": "nodemon server.js",
"fetch": "node fetch-data.js"
,
"keywords": [
"json-server,heroku, node, REST API"
],
"author": "Jesper Orb",
"license": "ISC",
"dependencies":
"google-spreadsheet": "^3.0.11",
"json-server": "^0.16.1"
【问题讨论】:
您能否展示您的整个目录结构,以便我们查看您服务器的服务器的server.js
和package.json
文件是在根文件夹中,还是在api 文件夹中?
是的,当然!我将它们添加到帖子中。
所以你没有 package.json 在根级别? api和client里面分别有2个package.json文件对吧?
是的,我每个都有一个 package.json 文件(一个在客户端的文件夹中,一个在 api 的文件夹中)。这两个都在根级别。但是 0 级(存在客户端和 api 文件夹)什么都没有。
如果您只想使用一个 Heroku 应用程序,我可以建议一种方法
【参考方案1】:
我看到你正在使用 json 服务器,所以你不需要使用 express 来服务你的静态资产,而是你需要将你的构建文件夹移动到项目的根级别并将其重命名为 public
以便 json -server 会看到它并根据their markdown on github服务它
-
将
api/package.json
和server.js
移动到应用程序的根级别。
为了移动您的client/build
文件夹(在从 ./client 运行 npm run build 之后)并将其重命名为 public,添加一个 heroku-postbuild 脚本到根 package.json 像这样
"heroku-postbuild": "cd client && npm install && npm install --only=dev --no-shrinkwrap && npm run build && mv -v build/ .. && cd .. && mv build public"
将您的主要 api url 添加到您的 react 应用程序中
client/.env.development
REACT_APP_BASE_URL=http://localhost:4000/api
client/.env.production
REACT_APP_BASE_URL=https://myapp.herokuapp.com/api
-
让
json-server
自动为您的静态前端文件提供服务。
【讨论】:
感谢您的详尽解释! 嘿,很抱歉再次打扰,但是 Heroku 上的部署很顺利,直到我收到 404 错误(nginx)。它是否与仍在文件夹“api”而不是项目根目录中的文件“server.js”有关? 您采用了哪种方法? 如果您采用第二种方法,您需要为客户端和服务器提供单独的 git 存储库,因为 heroku 一次只能看到一个应用程序 更准确地说,客户端运行良好,但 API 不行。它尝试连接到'localhost/3001/api',我怀疑 Axios 'baseURL' 设置为:'process.env.baseURL || 'localhost:3001/api''以上是关于在 Heroku 上部署 React 应用和 API 的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章
在 Heroku 上部署 React 应用和 API 的最佳实践
在heroku上部署Nodejs+Express+React+Webpack应用
在 Heroku 上部署 Django API + React 应用程序