У меня есть приложение для социальных сетей, где пользователь может войти в систему, а затем перейти к своей ленте, где они могут создавать сообщения, и они отображаются в ленте. Все работает на локальном хосте, но на сервере я могу войти в систему и увидеть ленту и даже могу создавать сообщения, которые сохраняются в базе данных, но они не отображаются в ленте на сервере.
Это server.js:
const path = require('path');
const express = require('express');
const cors = require('cors');
const fileUpload = require('express-fileupload');
const AuthRoute = require('./routes/AuthRoute.js');
const connectDB = require('./config/db.js');
const colors = require('colors');
const dotenv = require('dotenv');
dotenv.config();
const PostRoute = require('./routes/PostRoute.js');
const UploadRoute = require('./routes/UploadRoute.js');
const PORT = process.env.PORT || 8000;
connectDB();
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cors());
// Serve frontend
if (process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, '../frontend/build')));
app.get('*', (req, res) =>
res.sendFile(
path.resolve(__dirname, '../', 'frontend', 'build', 'index.html')
)
);
} else {
app.get('/', (req, res) => res.send('Please set to production'));
}
app.listen(PORT, () => {
console.info(`Server is running on port ${PORT}.`.yellow.bold);
});
app.use('/api/auth', AuthRoute);
app.use('/api/posts', PostRoute);
app.use('/api/uploadImages', UploadRoute);
Я пробовал перемещать вещи, но это ничего не изменило. Это мои PostRoutes:
const express = require('express');
const {
createPost,
getTimelinePosts,
getAllPosts,
} = require('../controllers/PostController.js');
const { authUser } = require('../middleware/auth');
const router = express.Router();
console.info('inside am in the routes');
router.post('/createPost', createPost);
router.get('/:id/timeline', getTimelinePosts);
router.get('/getAllPosts', authUser, getAllPosts);
module.exports = router;
Ниже показано, где они изначально вызываются и на локальном хосте, и если я прокомментирую весь код, кроме useEffect, он покажет массив сообщений в консоли, но в консоли сервера он покажет html-документ.
Вот файл:
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { getTimeLinePosts } from '../../../actions/postAction';
import Post from '../Post/Post.js';
import PulseLoader from 'react-spinners/FadeLoader';
const Posts = () => {
const dispatch = useDispatch();
const { user } = useSelector((state) => state.authReducer.authData);
const { posts, loading, error } = useSelector((state) => state.postReducer);
useEffect(() => {
if (error) {
console.info(error);
}
dispatch(getTimeLinePosts(user._id));
}, [dispatch, user._id]);
return (
<div className = "Posts">
{loading ? (
<div style = {{ display: 'flex', justifyContent: 'center' }}>
<PulseLoader
color = "#485639"
height = {15}
width = {5}
loading = {loading}
/>
</div>
) : posts ? (
posts.map((post, i) => (
<Post key = {i} post = {post} index = {i} user = {user} />
))
) : (
"You haven't shared anything yet."
)}
</div>
);
};
export default Posts;
Вот пост Запрос
import axios from 'axios';
//import * as PostsApi from '../api/PostsRequests';
export const getTimeLinePosts = (id) => async (dispatch) => {
console.info(id);
const API_URL = '/api/posts/';
dispatch({ type: 'RETREIVING_START' });
try {
//const { data } = await PostsApi.getTimelinePosts(id);
const { data } = await axios.get(`/api/posts/${id}/timeline`);
console.info(data);
dispatch({ type: 'RETREIVING_SUCCESS', data: data });
} catch (error) {
dispatch({ type: 'RETREIVING_FAIL' });
console.info(error);
}
};
А вот и постРедуктор
const postReducer = (
state = { posts: null, loading: false, error: false, uploading: false },
action
) => {
switch (action.type) {
// belongs to PostShare.jsx
case 'ADDPOST_START':
return { ...state, error: false, uploading: true };
case 'ADDPOST_SUCCESS':
return {
...state,
posts: [action.data, ...state.posts],
uploading: false,
error: false,
};
case 'ADDPOST_FAIL':
return { ...state, uploading: false, error: true };
// belongs to Posts.jsx
case 'RETREIVING_START':
return { ...state, loading: true, error: false };
case 'RETREIVING_SUCCESS':
return {
...state,
posts: action.data,
loading: false,
error: false,
};
case 'RETREIVING_FAIL':
return { ...state, loading: false, error: true };
default:
return state;
}
};
export default postReducer;
Краткий ответ: строки, обслуживающие статические ресурсы, должны быть размещены после всех остальных маршрутов в файле сервера.
Длинный ответ: Пожалуйста, введите следующие строки
// Serve frontend
if (process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, '../frontend/build')));
app.get('*', (req, res) =>
res.sendFile(
path.resolve(__dirname, '../', 'frontend', 'build', 'index.html')
)
);
после следующих строк:
app.use('/api/auth', AuthRoute);
app.use('/api/posts', PostRoute);
app.use('/api/uploadImages', UploadRoute);
Express JS интерпретирует маршруты на основе порядка их записи в файле сервера, поэтому статические ресурсы должны обслуживаться после всех остальных маршрутов. Это должно решить вашу проблему.
@JonePolvora, пожалуйста, еще раз прочитайте мой полный ответ.
Я не работал, но я поставил галочку, чтобы увидеть, получает ли страница posts.js какие-либо сообщения "posts && console.info(posts)". Он по-прежнему просто печатает html, но печатает его три раза, если это имеет значение.
Это действительно сработало. Что-то случилось, и мне пришлось перестроить сервер, и когда я это сделал, ваше решение сработало. Спасибо!
Проблема в том, что вы условно добавляете обработчик перехвата всех сообщений app.get("*")
в экспресс-конвейер, что сделает ваши маршруты API недоступными. Промежуточное ПО express.static
уже обрабатывает пути, сопоставленные с физическими файлами, и в случае, если файл не найден, оно просто передает запрос следующему промежуточному ПО.
Возможным исправлением может быть рефакторинг кода, может быть, просто удалить проверку на производство и обработчик улавливания всех.
Обратите внимание, что маршруты API должны быть установлены до вызова app.listen()
.
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cors());
// Serve frontend
app.use(express.static(path.join(__dirname, '../frontend/build')));
app.use('/api/auth', AuthRoute);
app.use('/api/posts', PostRoute);
app.use('/api/uploadImages', UploadRoute);
app.listen(PORT, () => {
console.info(`Server is running on port ${PORT}.`.yellow.bold);
});
Я не знаю, почему вы используете режим производства в NODE_ENV, приложение должно работать в любой среде.
Я не работал. Я действительно думаю, что это имело значение, раньше в devtools в редукции postReducer всегда был нулевым на сервере, не имеет значения, а публикуется html. Я поставил галочку, чтобы увидеть, получала ли страница posts.js какие-либо сообщения «posts && console.info(posts)». Он по-прежнему просто печатает html, но печатает его три раза, если это имеет значение.
вам нужно увидеть вкладку сети, если там выполняются запросы ajax (fetch/xhr) и если консоль выдает сообщения об ошибках.
На вкладке сети показано, что запрос был сделан со статусом 200, и URL-адрес запроса: 173.255.205.85/api/posts/643f61f952518863942e7677/timeline Метод запроса: GET Код состояния: 200 OK Удаленный адрес: 173.255.205.85:80 Политика реферера: строгое происхождение при перекрестном происхождении
А как насчет содержания ответа? Что исходит от ответа сети (загляните на вкладку сети)
вероятно, результатом контента является содержимое index.html, поэтому, как я уже сказал выше, удаленный маршрут app.get("*"). Все запросы на получение вернут один и тот же результат
Я это сделал. У меня есть то, что вы опубликовали, но все еще получаю index.html.
наконец-то я нашел причину проблемы. Проблема заключается в путях обслуживания статических файлов, вашей структуре каталогов, возможно, в вашем webpack.config.
Но как я могу определить проблему и исправить ее. Я не изменил файловую структуру. Я создал интерфейс с помощью приложения create-реагировать.
пожалуйста, отредактируйте свой вопрос, рассказав нам, как устроены ваши каталоги.
Нет, сначала мы должны проверить, есть ли совпадения для физических файлов через express.static miiddleware, а затем мы отвечаем на http-запросы.