Невозможно получить ответ JSON от Express в рабочей среде

#javascript #json #reactjs #express

#javascript #json #reactjs #экспресс

Вопрос:

В режиме разработки react и express подключаются идеально, и я могу извлекать данные из серверной части. Но при использовании их в рабочем режиме я получаю статус 200, но не могу получить ответ json от express.

Я получаю эту ошибку:

 SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
  

Серверный файл — это:

 const express = require('express');
const bodyParser = require("body-parser");
const cors = require("cors");
const path = require("path");
const helmet = require("helmet");
const compression = require("compression");

if(process.env.NODE_ENV !== "production") require('dotenv').config();

const app = express();

//middlewares
app.use(helmet());
app.use(compression());
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));


// serve the react app files in production
if(process.env.NODE_ENV === "production") {
    app.use(express.static(path.join(__dirname, "client/build")));

    app.get("*", (req, res) => {
        res.sendFile(path.join(__dirname, "client/build", "index.html"))
    })
}

//port
const port = process.env.PORT || 5000;
app.listen(port, error => {
    if(error) throw error;
    console.log(`Backend is running on localhost:${port}`);
});

// connection route
app.get("/express", (req, res) => res.json({express: "YOUR EXPRESS BACKEND IS CONNECTED"}));
  

Серверный package.json:

 {
  "name": "",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "engines": {
    "node": "12.19.0",
    "npm": "6.14.8"
  },
  "scripts": {
    "test": "echo "Error: no test specified" amp;amp; exit 1",
    "start": "nodemon server.js",
    "mainstart": "concurrently --kill-others-on-fail "npm start" "cd client amp;amp; yarn start""
  },
  "repository": {
    "type": "git",
    "url": "git https://github.com/g4rry420/armourLine.git"
  },
  "author": "Gurkiran Singh",
  "license": "ISC",
  "bugs": {
    "url": ""
  },
  "homepage": "",
  "dependencies": {
    "body-parser": "^1.19.0",
    "compression": "^1.7.4",
    "concurrently": "^5.3.0",
    "cors": "^2.8.5",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "helmet": "^4.2.0",
    "nodemon": "^2.0.6",
    "path": "^0.12.7"
  }
}
  

Интерфейс App.js

 import React,{ useEffect, useState } from 'react';
import { Route, Switch } from "react-router-dom"

import './App.css';
import Header from "./components/header/header.component"
import ProductItem from './components/product-item/product-item.component';
import Homepage from './pages/homepage.component';
import ProductForm from "./components/product-form/product-form.component";

function App() {

  const [backendData, setBackendData] = useState("No Fetching")

  useEffect(() => {
    callBackedApi()
      .then(res => setBackendData(res.express))
      .catch(err => console.log(err))
  }, [])

  async function callBackedApi(){
    
    const response = await fetch("/express", {
      headers: {
        'Content-Type': 'application/json',
      },
    })
  
    const body = await response.json();

    if(response.status !== 200){
      throw Error(body.message)
    }
    return body;
  }

  return (
    <div className="App">
      {backendData}
      <Header />
      <div>
        <Switch>
          <Route exact path="/" component={Homepage} /> 
          <Route path="/product" component={ProductItem} />
          <Route path="/product-form" component={ProductForm} />
        </Switch>
      </div>
    </div>
  );
}

export default App;
  

Внешний интерфейс package.json

 {
  "name": "armourline",
  "version": "0.1.0",
  "private": true,
  "proxy": "http://localhost:5000",
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "bootstrap": "^4.5.2",
    "react": "^16.13.1",
    "react-bootstrap": "^1.3.0",
    "react-dom": "^16.13.1",
    "react-icons": "^3.11.0",
    "react-router-dom": "^5.2.0",
    "react-scripts": "3.4.3",
    "react-slick": "^0.27.13"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "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"
    ]
  }
}

  
  

Ответ №1:

У вас проблема с упорядочением маршрута.

В рабочей среде этот код активен:

 // serve the react app files in production
if(process.env.NODE_ENV === "production") {
    app.use(express.static(path.join(__dirname, "client/build")));

    app.get("*", (req, res) => {
        res.sendFile(path.join(__dirname, "client/build", "index.html"))
    })
}
  

Который помещает app.get("*", ...) маршрут ПЕРЕД вашим app.get("/express", ...) маршрутом, поэтому * route перехватит запрос и отправит его в формате HTML, который не будет анализироваться как JSON. Порядок ваших маршрутов имеет значение, когда они могут конфликтовать.

Переместите свой app.get("/express", ...) маршрут ПЕРЕД своим app.get("*", ...) маршрутом, фактически, маршрут *, вероятно, должен быть последним, чтобы все индивидуально указанные маршруты получили шанс перехватить запрос до того, как это сделает маршрут *. Лично я сам не использую * routes из-за некоторых проблем, которые они могут вызвать.

Комментарии:

1. а что, если я захочу добавить какие-либо дополнительные маршруты, должен ли я также добавить их два раза, один в рабочей среде и один в разработке?

2. @GurkiranSingh — Я никогда не предлагал вам добавлять маршрут два раза. Я предположил, что вам нужно добавлять маршруты в правильном порядке, когда у вас есть перекрывающиеся определения маршрутов.

3. @GurkiranSingh — Чтобы мы могли помочь вам в дальнейшем, нам нужно больше информации, которая «все еще не работает». Вам нужно посмотреть на фактический ответ, который вы получаете с console.log() помощью отладчика, и посмотреть, что именно это такое, и поделиться этим с нами.

4. @GurkiranSingh — Это ответило на ваш вопрос? Если это так, вы можете сообщить об этом сообществу, щелкнув галочку слева от ответа, и это также принесет вам несколько очков репутации за соблюдение надлежащей процедуры.