Vite React Redux Toolkit,api端点用我自己的index.html文件响应

问题描述 投票:0回答:1

我正在学习全栈开发,最近将我的项目(一个基本的 meern 堆栈)从 create-react-app 切换到 Vite,这样我就可以配置和使用 vitests 与 React-testing-library 的兼容性。在遵循这篇文章text和其他一些文章之后,运行 npm run dev 启动服务器,连接到数据库,并在浏览器中拉出我的项目。

问题在于,对后端的任何请求都会被(我的中间件?、RTK 错误处理?)拦截,并且发送回前端的响应是我自己的 index.html 文件。 index.html 文件位于前端的根目录中,与 vite.config.js 处于同一级别。将其放入公共文件夹会使我的浏览器崩溃,如此处所述text

我可以使用 useEffect 从前端手动查询后端并很好地获取。服务器在 localhost:5000 上运行得很好,并且在使用邮递员时我得到了预期的响应。我可以在控制器中 console.log 响应,然后得到预期的数据。我已经添加了这里text和这里text提到的responseHandler,它删除了这个错误:,以及我的控制台中的解析错误,但现在我的redux查询中的错误只是未定义。我尝试了多种方式配置我的 vite.config.js,我也从我的 package.json 中删除了代理,但没有成功。我还添加了 cors 包并在我的 server.js 文件中使用。

我知道 vite 以不同的方式处理环境变量,但我不认为这是问题,因为我的前端文件夹与后端完全分开,并且只有后端使用 .env 文件中的变量。

在此项目的 create-react-app 版本中一切都按预期工作。

这篇文章text描述了我遇到的相同错误,我尝试实施建议的解决方案,但没有成功。

正如之前提到的,我认为这很可能是由于 RTK 抛出错误,因为它不喜欢我的服务器的响应。这是我认为的所有相关代码。

vite.config.js

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

import dns from "dns";

// localhost part
// dns.setDefaultResultOrder("verbatim");

export default defineConfig(() => {
    return {
        plugins: [react()],
        server: {
            open: true,
            // host: "127.0.0.1",
            port: 3000,
            proxy: {
                "/api": {
                    target: "http://localhost:5000",
                    changeOrigin: true,
                    rewrite: (path) => path.replace(/^\/api/, ""),
                },
            },
        },

        build: {
            manifest: true,
            rollupOptions: {
                input: "./src/App.jsx",
            },
        },

        resolve: {
            alias: [
                {
                    // this is required for the SCSS modules
                    find: /^~(.*)$/,
                    replacement: "$1",
                },
            ],
        },
    };
});

控制器中的代码


    const getSectionByUrl = asyncHandler(async (req, res) => {
    // const section = recursiveSearch(menuItems, 
    req.params.sectionId);

    const section = await Section.find({ url: req.params.sectionId });
    // console.log(section[0], "section in secitonRoutes");
    if (section) {
        // console.log(res.json(section[0]), "controller");
        return res.json(section[0]);
    } else {
        res.status(404);
        throw new Error("Section not found");
    }
});

带有端点的sectionApiSlice.js

    import { SECTIONS_URL } from "../constants";
    import { apiSlice } from "./apiSlice";

    export const sectionsApiSlice = apiSlice.injectEndpoints({
        endpoints: (builder) => ({
            getSections: builder.query({
                query: () => ({
                    url: SECTIONS_URL,
                }),

                keepUnusedDataFor: 5,
            }),
            getSectionByUrl: builder.query({
                query: (sectionUrl) => ({
                    url: `${SECTIONS_URL}/${sectionUrl}`,
                    responseHandler: "text",
                }),
                keepUnusedDataFor: 5,
            }),
            getQuizBySectionKey: builder.query({
                query: (sectionKey) => ({
                    url: `${SECTIONS_URL}/quiz/${sectionKey}`,
                }),
            }),
        }),
    });

    export const {
        useGetSectionsQuery,
        useGetSectionByUrlQuery,
        useGetQuizBySectionKeyQuery,
    } = sectionsApiSlice;

服务器.js


    import express from "express";
    import cors from "cors";
    import dotenv from "dotenv";
    import cookieParser from "cookie-parser";
    import bodyParser from "body-parser";
    dotenv.config();
    import connectDB from "./config/db.js";
    import { notFound, errorHandler } from "./middleware/errorMiddleware.js";
    import sectionRoutes from "./routes/sectionRoutes.js";
    import userRoutes from "./routes/userRoutes.js";
    const port = process.env.PORT || 5000;
    
    connectDB();
    
    const app = express();
    app.use(cors()); // This will enable CORS for all routes
    //Body parser middleware
    
    app.use(express.json());
    app.use(bodyParser.json());
    app.use(express.urlencoded({ extended: true }));
    
    //Cookie parser middleware. Allows to access cookies
    app.use(cookieParser());
    
    app.get("/", (req, res) => {
        res.send("API is running...");
    });
    
    app.use("/sections", sectionRoutes);
    app.use("/users", userRoutes);
    
    //use errorMiddleware
    app.use(notFound);
    app.use(errorHandler);
    
    app.listen(port, () => console.log(`Server running on port ${port}`));

前端package.json中的脚本

    "scripts": {
        "sass:build": "sass scss:css",
        "start": "vite",
        "build": "vite build",
        "serve": "vite preview",
        "dev": "vite --host localhost --port 3000"
    },

自定义错误处理,我认为这无关紧要,只是以防万一


    const notFound = (req, res, next) => {
    const error = new Error(`Not Found - ${req.originalUrl}`);
    res.status(404);
    next(error);
    };

    const errorHandler = (err, req, res, next) => {
        //if an error but statusCode is still 200
        let statusCode = res.statusCode === 200 ? 500 : 
    res.statusCode;
        let message = err.message;
    
        //check for mongoose bad ObjectId
        if (err.name === "CastError" && err.kind === "ObjectId") {
            message = `Resource not found`;
            statusCode = 404;
        }
    
        res.status(statusCode).json({
            message,
            stack: process.env.NODE_ENV === "production" ? "🥞" : 
    err.stack,
        });
    };
    
    export { notFound, errorHandler };

reactjs node.js express redux vite
1个回答
0
投票

在这篇文章here的帮助下,我终于让它工作了,并进行了大量的试验和错误。事实证明,我的问题是我的前端和后端路径彼此没有区别,因此一旦我在后端使用的路由前面加上“/api/”(如“/api/sections”中所示),并更新了我的一些设置代理,一切似乎都按预期进行,至少在开发中是这样。这是修改后的 vite.config.js:


    import { defineConfig } from "vite";
    import react from "@vitejs/plugin-react";
    
    import dns from "dns";
    
    dns.setDefaultResultOrder("verbatim");
    export default defineConfig(() => {
        return {
            plugins: [react()],
            server: {
                open: true,
                port: 3000,
                proxy: {
                    "/api": {
                        target: "http://localhost:5000",
                        changeOrigin: true,
                        ws: true,
                        secure: false,
                        rewrite: (path) => path.replace(/^\/api/, ""),
                    },
                },
            },
    
            build: {
                manifest: true,
                rollupOptions: {
                    input: "./src/App.jsx",
                },
            },
    
            resolve: {
                alias: [
                    {
                        // this is required for the SCSS modules
                        find: /^~(.*)$/,
                        replacement: "$1",
                    },
                ],
            },
        };
    });

© www.soinside.com 2019 - 2024. All rights reserved.