我试图部署一个MERN应用程序(与create react app构建)到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
Proxy (in 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)
})
})
你有两个选择,
#1 -使所有的url相对,例如fetch('/api/all-reviews')
,并有两个前端和后端运行在同一台服务器上。使用express.static
中间件从后端提供静态构建文件(在运行npm run build
之后可以在build
文件夹中找到,假设您使用的是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'));