我正在学习全栈开发,最近将我的项目(一个基本的 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 };
在这篇文章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",
},
],
},
};
});