提问者:小点点

我的CRUD应用程序可以在本地运行,但不能在Heroku上运行


我已经创建了一个CRUD应用程序,它可以在本地运行,但我不能让它在Heroku上运行良好。 它部署正确,网站似乎工作,但然后我不能得到我需要的项目从数据库,因为它一直说连接拒绝。 我向Heroku添加了。env变量,并将端口设置为process.env.port5000app.listen(port),但我不确定是什么导致了这个错误。 我还有一个带有web:nodeServer.js的Procfile,以及package.json中指向Server.js的“start”脚本。 服务器似乎根本就没有启动。
这里是repo,如果你想看看https://github.com/thomyorke7/inventory,这里是heroku上的app https://boardgamenerd.herokuapp.com/


共1个答案

匿名用户

问题在于您的应用程序有一个后端(服务器)和一个前端(客户机),它们在本地的服务方式与在Heroku上的服务方式不同。

我假设您的客户端在本地运行在localhost:3000上(因为它是您引导的create-react-app的默认值)。 当您的后端在localhost:5000上运行时,您的客户机的package.json包含这一行以使其在本地工作:

"proxy": "http://localhost:5000",

如果我访问您应用程序的此页面:https://boardgamenerd.herokuapp.com/>; boardgames,然后我在浏览器控制台面对这些错误:

boardgames-list.jsx:18

Error: Network Error
    at e.exports (createError.js:16)
    at XMLHttpRequest.p.onerror (xhr.js:83)
xhr.js:178

GET http://localhost:5000/boardgames/ net::ERR_CONNECTION_REFUSED

它告诉您,您的生产版本仍然调用localhost:5000上的后端。

I.)首先,我尝试通过更改为相对URL来修复这些获取。

例如。 上面的例子(boardgames-list.jsx:18)

当前脚本已硬编码localhost fetch:

useEffect(() => {
    axios
      .get('http://localhost:5000/boardgames/')
      .then((response) => {
        setBoardgames(response.data);
        setLoading(false);
      })
      .catch((err) => console.log(err));
  }, []);

通过删除“http://localhost:5000”使其相对于root用户:

useEffect(() => {
    axios
      .get('/boardgames/')
      .then((response) => {
        setBoardgames(response.data);
        setLoading(false);
      })
      .catch((err) => console.log(err));
  }, []);

对Heroku也有效。 如果它不会:请看下面我的建议。

ii.)其次,建议:现在您的https://boardgamenerd.herokuapp.com/boardgames路由使用以下后端端点来获取数据:https://boardgamenerd.herokuapp.com/boardgames/

区别仅仅是最后一个斜杠(“/”)字符,这个字符可能会让人迷惑,并在以后引起更多的问题! 将微分器路径元素添加到后端端点是一种最佳实践,如/api/。 例如:https://boardgamenerd.herokuapp.com/api/boardgames,因此您可以第一眼就确定哪些get请求与后端相关,哪些请求与客户端相关。

如果使用此解决方案,则需要将以下内容添加到server.js:

app.use(express.static(path.join(__dirname, 'client', 'build')))
    // required to serve SPA on heroku production without routing problems; it will skip only 'api' calls
    if (process.env.NODE_ENV === 'production') {
      app.get(/^((?!(api)).)*$/, (req, res) => {
        res.sendFile(path.join(__dirname, 'client/build', 'index.html'))
      })
    }

/^((?!(api)).)*$/regex会跳过路径中包含“api”的URL,因此它们不会以静态方式提供,因为客户端/构建文件夹的内容api调用不会从静态方式提供,因此可以正常工作。