【问题标题】:After deploying React app to Heroku from dev env, Fetch requests broken - all GET requests returning index.html - others are 404从 dev env 将 React 应用程序部署到 Heroku 后,Fetch 请求中断 - 所有 GET 请求都返回 index.html - 其他是 404
【发布时间】:2019-02-19 19:01:51
【问题描述】:

我刚刚将我的 Create-React-App 项目部署到 Heroku。在开发中,我运行了两个单独的端口 - 本地 HTML + JS 使用端口 3000 上的 npm/yarn start 脚本从 React WebpackDevServer 提供服务。后端是在端口 3001 上运行的 Express + NodeJS。我配置了所有获取请求使用mode:'cors' 并在API 上提供了一个处理程序以避免CORS 错误。 典型的 fetch 请求如下所示:

当我部署到 Heroku 时,所有内容现在都保存在一个 Dyno 上,Express 应用程序提供 React 文件(bundle + index.html)并处理后端路由逻辑。

到目前为止,这是我的 API 代码示例:

const express = require('express');
const mongoose = require('mongoose');
const path = require('path');
const bodyParser = require('body-parser');
const config = require('./models/config');
require('dotenv').config()
const app = express();
const server = require('http').createServer(app);

const storeItems= require('./controllers/storeItems')
const authorize= require('./controllers/authorize')
const router = express.Router(); 

mongoose.Promise = global.Promise; 
mongoose.connect(`mongodb://${process.env.MLABS_USER}:${process.env.MLABS_PW}@ds113000.mlab.com:13000/omninova`, { useMongoClient: true });

app.use(bodyParser.json());

// Middleware to handle CORS in development:

app.use('/*', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, x-access-token, x-user-pathway, x-mongo-key, X-Requested-With, Content-Type, Accept");
  res.header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
  next();
});

app.use(express.static(path.join(__dirname, 'client/build')));

router.route('/api/storeItem/')
    .get(storeItems.getAllStoreItems)
    .post(storeItems.createNewStoreItem);

router.route('/authorize')
    .post(authorize.login);

// Catch-All Handler should send Client index.html for any request that does not match previous routes

router.route('*')
    .get((req, res) => {
        res.sendFile(path.join(__dirname+'/client/build/index.html'));
    });

app.use('/', router);

server.listen(config.port);
module.exports = app;

我遇到了一些问题,我所有的 get 请求都返回了我的 index.html 页面,并出现以下错误:Unexpected token < in JSON at position 0

我有以下获取请求:

    return fetch(`/api/storeItem`, {
        headers:{
            'Content-Type': 'application/json',
        },
        method: 'GET',
        mode: 'no-cors',
    })
    .then(response => response.ok ? response.json() : Promise.reject(response))
    .then(json => {
        dispatch(receiveItems(json))
    })
    .catch(err => console.log(err))

这是失败的,因为它没有触发应该在后端运行 storeItems.getAllStoreItems 的 Express 中间件,而是传递了该路由并触发了 catch-all 处理程序,我用它来根据初始请求为 index.html 提供服务:

router.route('*')
    .get((req, res) => {
        res.sendFile(path.join(__dirname+'/client/build/index.html'));
    });

另一个混淆是下面的 fetch 请求返回 404,即使 /authorize 路由在 API 代码中期待 POST 请求:

export function attemptLogIn(credentials) {
    return dispatch => {
        return fetch('/authorize', {
        headers:{
            'Content-Type': 'application/json'
        },
        method: 'POST',
        mode: 'no-cors'
        body: JSON.stringify(credentials)
        })
        .then(response => response.ok ? response.json() : Promise.reject(response.statusText))
        .then(json => {
            dispatch(routeUserAfterLogin(json.accountType))
        })
        .catch(err => dispatch(authFail(err.message)))
    }
} 

对此的任何帮助将不胜感激。我假设我在 Express 路由器上做错了,因为授权路由没有被拾取。

我按照这篇博文中的说明帮助我设置了新项目:https://daveceddia.com/deploy-react-express-app-heroku/

编辑:这是从我的开发分支获取代码。这成功地使用户登录,而没有返回 404。但是,我根本不使用 catch-all 处理程序或 express.static 中间件:

return fetch('http://localhost:3001/authorize', {
    headers:{
        'Content-Type': 'application/json'
    },
    method: 'POST',
    mode: 'cors', 
    body: JSON.stringify(credentials)
})

编辑:我刚刚将指向 bundle.js 的 URL 更改为 app.use(express.static(path.join(__dirname, '/../../build'))); 我不确定我之前是如何发送 HTML 的,因为那是构建文件的实际位置。我不确定之前是如何找到它们的。

Edit2:发现我的问题,我留在了我的 React 项目的启动脚本中(实际上启动了 webpack 开发服务器......)

【问题讨论】:

    标签: node.js reactjs express heroku deployment


    【解决方案1】:

    这应该可以解决问题。应该用“/”代替“*”。现在我的 GET 请求就像 Heroku 上的 POST 一样工作。

    https://stackoverflow.com/a/37878281/12839684

    【讨论】:

    • 你救了我!非常感谢你,我终于可以睡觉了:)
    【解决方案2】:

    您的服务器发送的不是 json 响应而是 HTML 内容。将响应更改为 res.text() 并记录它。 https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

    router.route('*')
        .get((req, res) => {
            res.sendFile(path.join(__dirname+'/client/build/index.html'));
        });
    

    【讨论】:

      【解决方案3】:

      第一部分

      错误:JSON 中位置 0 处的意外标记

      我的猜测是,如果没有开发服务器,express 无法自动处理捆绑下载。因此,当您的 index.html 命中 /path/to/bundle.js 时,它属于通配符 ("*") 路由,该路由返回 HTML 本身。然后您的浏览器尝试将其解析为 JS,但由于它是 HTML,因此无法解析,因此出现错误。

      我会尝试类似:

      app.get("path/to/bundle.js", (req, res) => {
        res.sendFile("path/to/bundle.js");
      });
      

      【讨论】:

      • Tyvm 为您解答!在我的 Heroku 日志中,我可以看到包已下载:heroku[router]: at=info method=GET path="/static/js/bundle.js" host=still-beach-13809.herokuapp.com request_id=9... dyno=web.1 connect=0ms service=9ms status=304 bytes=176 protocol=http。如果 bundle.js 不存在,我认为我无法访问我的 React Javascript 代码(获取请求等),我还可以在 Sources 选项卡中看到 bundle.js。我相信问题是应该去/storeItems的获取请求(GET)仍然去那个通配符路由并触发res.sendFile(index.html)
      • 嗯,我明白了。但是这个快速配置是在本地工作而不是在产品上工作?相同的代码?因为它在我看来还不错
      • 我在 dev 中没有以下代码:app.use(express.static(path.join(__dirname, 'client/build')));router.route('*') .get((req, res) => { res.sendFile(path.join(__dirname+'/client/build/index.html')); }); 在 prod。在我添加之后,我所有的 GET 请求都会触发这个。
      • 我会尝试将这一行 app.use(express.static(path.join(__dirname, 'client/build'))); 移动到 router.route('*') 之前,并确保通配符路由是最后一个定义的 - 表达顺序很重要
      • 我不知道为什么它不工作 :( 我有以下 3 条路线:app.get('/storeItem/', storeItems.getAllStoreItems); app.use(express.static(path.join(__dirname, 'client/build'))); app.get('*', (req, res) => {res.sendFile(path.join(__dirname+'/client/build/index.html'));});。现在,这是我的获取......它应该可以工作检索 JSON,但它得到 HTML return fetch('/storeItem/', {headers:{'Content-Type': 'application/json',},method: 'GET',mode: 'no-cors',})。仍然不明白为什么它没有被正确匹配。可能是我的代码/构建有一些代理问题或错误
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-03
      • 1970-01-01
      • 2015-11-14
      • 1970-01-01
      • 2014-06-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多