在 Heroku 上部署 React 应用程序和 API 的最佳实践
Best practices to deploy a React app and an API on Heroku
我目前正在为 API.
使用 React(通过 create-react-app
)和 JSONServer 开发一个项目
我有一个 Git 存储库,其结构如下:
|-- client
|-- api
为了在开发环境中工作,我使用 npm start
启动两个文件夹,以便为 React 应用程序提供 http://localhost:3000,为 API.
这样(感谢 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 创建一个应用程序并将客户的构建放在同一个 folder/url
(例如:使用 JSONServer 提供构建的 public 文件)
目前,我在客户文件夹的根目录下有一个 server.js
文件,还有一个 Procfile
和 web: node server.js
来启动构建服务器。然后我使用 Axios 从另一个 Heroku 应用程序(实际上是 API 应用程序)获取数据。
任何 advice/help 将不胜感激!谢谢!
P.S.: 这是我的 package.json ans 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"
}
}
我看到你正在使用 json 服务器,所以你不需要使用 express 来为你的静态资产提供服务,而是需要将你的构建文件夹移动到项目的根级别并将其重命名为public
这样 json-server 就会看到它并根据 their markdown on github
提供服务
- 将您的
api/package.json
和 server.js
移动到应用程序的根级别。
- 为了移动你的
client/build
文件夹(在 运行ning npm 运行 build from ./client 之后)并将其重命名为 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 应用
客户端/.env.development
REACT_APP_BASE_URL=http://localhost:4000/api
客户端/.env.production
REACT_APP_BASE_URL=https://myapp.herokuapp.com/api
- 并让
json-server
自动为您的静态前端文件提供服务。
我目前正在为 API.
使用 React(通过create-react-app
)和 JSONServer 开发一个项目
我有一个 Git 存储库,其结构如下:
|-- client
|-- api
为了在开发环境中工作,我使用 npm start
启动两个文件夹,以便为 React 应用程序提供 http://localhost:3000,为 API.
这样(感谢 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 创建一个应用程序并将客户的构建放在同一个 folder/url (例如:使用 JSONServer 提供构建的 public 文件)
目前,我在客户文件夹的根目录下有一个 server.js
文件,还有一个 Procfile
和 web: node server.js
来启动构建服务器。然后我使用 Axios 从另一个 Heroku 应用程序(实际上是 API 应用程序)获取数据。
任何 advice/help 将不胜感激!谢谢!
P.S.: 这是我的 package.json ans 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"
}
}
我看到你正在使用 json 服务器,所以你不需要使用 express 来为你的静态资产提供服务,而是需要将你的构建文件夹移动到项目的根级别并将其重命名为public
这样 json-server 就会看到它并根据 their markdown on github
- 将您的
api/package.json
和server.js
移动到应用程序的根级别。 - 为了移动你的
client/build
文件夹(在 运行ning npm 运行 build from ./client 之后)并将其重命名为 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 应用
客户端/.env.development
REACT_APP_BASE_URL=http://localhost:4000/api
客户端/.env.production
REACT_APP_BASE_URL=https://myapp.herokuapp.com/api
- 并让
json-server
自动为您的静态前端文件提供服务。