我正在尝试将一个 MERN 应用(使用 create react 应用构建)部署到 Heroku,但是每当我尝试访问应用 URL 时,它都会返回 404 错误。
我检查了 Heroku 错误日志,它返回了以下错误:
app[web.1]: ls: cannot access '/app/build/static/js/*.js': No such file or directory
Error injecting runtime env: bundle not found '/app/build/static/js/*.js'. See: https://github.com/mars/create-react-app-buildpack/blob/master/README.md#user-content-custom-bundle-location
我已经构建了我的项目,以便它在两个不同的服务器上运行:客户端在 localhost:3000 上,它代理在 localhost:5000 上表达的请求。
我已经运行了 npm run build
,设置了静态中间件,并尝试正确配置我的 api 调用/路由,但它仍然无法正常工作。关于为什么以及如何解决它的任何建议?详情如下:
项目结构
+client
|
+-build
+-static
+-css
+-js
+-media
+-node_modules
+-public
+-src
|
+-components
+-App.js
+-index.js
//server
+-models
+-node-modules
+-package-lock.json
+-package.json
+-server.js
代理(在 package.json 中):
"proxy": "http://localhost:5000"
Heroku 构建脚本(在 client/package.json 中):
"scripts": {
"start": "react-scripts start",
"heroku-postbuild": "cd client && npm install --only=dev && npm install && npm run build",
服务器配置:
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Listening on port ${port}`));
//Middleware
app.use(express.static(path.join(__dirname, 'client/build')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.urlencoded())
app.use(cors())
app.get('*', (req,res) =>{
res.sendFile(path.join(__dirname+'/client/build/index.html'));
});
以下是我构建 API 的方式。注意:我已经从我的 axios 请求的 URL 中删除了“localhost:5000”:
来自 React 组件的 API 调用:
useEffect(() => {
axios.get('/api/all-reviews')
.then(review => {
setReviews(review.data)
})
.catch(err => {
console.log(err)
})
},[])
对应的快车路线
app.get('/api/all-reviews', (req,res) => {
Review.find()
.then((result) => {
res.send(result)
})
.catch(err => {
console.log(err)
})
})
答案 0 :(得分:1)
你有两个选择,
#1 - 使所有 url 相对,例如fetch('/api/all-reviews')
,并使前端和后端运行在同一台服务器上。使用 build
middleware 从后端提供静态构建文件(在运行 npm run build
后位于 express.static
文件夹中,假设您使用的是 create-react-app)。
请注意,您可以在生产中执行此操作,同时在开发中仍使用 process.env.NODE_ENV
依赖代理。一个示例实现是
// put this at the end of your server.js file
if (process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, '../client/build')));
}
#2 - 在不同的服务器上运行后端和前端,只需根据代码是在开发还是生产中运行来调整路径 举个例子:
const prefix = process.env.NODE_ENV === 'production' ? "http://heroku_app_address" : "http://localhost:5000"
function getUrl(relativeUrl) {
return prefix + "/" + relativeUrl;
}
fetch(getUrl('api/all-reviews'));