You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从零搭建React+Koa项目及React打包Windows exe方案咨询

代码问题修正说明

后端部分

server.js

  • 挂载vehicleRouter时,allowedMethods()错误引用了userRouter,应改为:
    app.use(vehicleRouter.routes()) 
        .use(vehicleRouter.allowedMethods());
    
  • dbConnect中mongoose.connect的回调参数错误,原代码把连接对象当成参数,实际应为错误对象,修正后:
    const dbConnect = () => {
        const dbConStr = process.env.MONGODB_URL;
        mongoose.connect(dbConStr)
            .then(() => console.log("MongoDB Connection Success"))
            .catch(err => console.error("MongoDB Connection Failed:", err));
    }
    

控制器(user.controller.js)

  • getAllUsers混合使用await和then/catch,简化为try/catch更规范:
    const getAllUsers = async (ctx) => {
        try {
            const users = await User.find();
            ctx.body = users;
        } catch (err) {
            console.log(err);
            ctx.body = { status: "error occured" };
            ctx.status = 500;
        }
    }
    
  • addUser中Content-Type拼写错误,应为application/json;且无需先创建new User,直接用User.create传对象即可:
    const addUser = async (ctx) => {
        const { id, name, email, password } = ctx.request.body;
        try {
            const user = await User.create({ id, name, email, password });
            ctx.body = user;
            ctx.set('Content-Type', 'application/json');
            ctx.status = 201;
        } catch (err) {
            console.log(err);
            ctx.body = { status: "error occured" };
            ctx.set('Content-Type', 'application/json');
            ctx.status = 500;
        }
    }
    
  • updateUser和deleteUser使用findByIdAndUpdate/findByIdAndDelete是按MongoDB自带的_id操作,但你的模型里自定义了id字段,若前端传递的是自定义id,需改为按自定义id查询:
    // updateUser修正
    const updateUser = async (ctx) => {
        const uid = ctx.params.id;
        const { id, name, email, password } = ctx.request.body;
        const updateUser = { id, name, email, password };
        try {
            await User.findOneAndUpdate({ id: uid }, updateUser, { new: true });
            ctx.body = { status: "User Updated" };
        } catch (err) {
            console.log(err);
            ctx.body = { status: "Error occured" };
            ctx.status = 500;
        }
    }
    
    // deleteUser修正
    const deleteUser = async (ctx) => {
        const uid = ctx.params.id;
        try {
            await User.findOneAndDelete({ id: uid });
            ctx.body = { status: "User Deleted" };
        } catch (err) {
            console.log(err);
            ctx.body = { status: "Error occured" };
            ctx.status = 500;
        }
    }
    
  • login中明文存储/校验密码极其不安全,需用bcrypt加密:
    1. 安装依赖:npm install bcrypt
    2. 注册用户时加密密码:const hashedPassword = await bcrypt.hash(password, 10);,存储hashedPassword而非明文
    3. 登录时校验:const isMatch = await bcrypt.compare(password, user.password);,用isMatch替代直接相等判断
  • auth函数使用了Express风格的req/res,Koa应使用ctx对象:
    const auth = async (ctx) => {
        const token = ctx.headers['x-access-token'];
        try {
            const decoded = jwt.verify(token, 'SecretKey123'); // 注意密钥要和login里的一致
            const user = await User.findById(decoded._id);
            ctx.body = { status: 'ok', name: user.name, id: user._id, uid: user.id, user: user };
        } catch (error) {
            console.log(error);
            ctx.body = { status: 'error', error: 'invalid token' };
            ctx.status = 401;
        }
    }
    

路由(user.router.js)

  • auth路由路径缺少斜杠,应改为:
    userRouter.post('/auth', auth);
    

模型(user.model.js)

  • 自定义id字段多余,MongoDB会自动生成_id作为唯一标识,可删除该字段,避免冲突。

前端部分

所有JSX标签缺少尖括号,这是语法错误,必须修正,例如:

  • App.js中:
    function App() {
      return (
        <div className='container'>
            <HeaderComponent />
            <Router>
                <Routes>
                    <Route exact path="/" element={<Users />}/>
                    <Route exact path="/register" element={<Register />}/>
                    <Route exact path="/login" element={<Login />}/>
                </Routes>
            </Router>
        </div>
      );
    }
    
  • Login.jsx和Register.jsx同理,所有<div>、<h2>、<form>等标签都需添加尖括号。
  • 登录跳转建议使用react-router-dom的useNavigate钩子替代window.location,避免页面刷新:
    import { useNavigate } from 'react-router-dom';
    
    function Login() {
        const navigate = useNavigate();
        // ...
        function loginUserHandler(e) {
            e.preventDefault();
            const user = { email, password };
            axios.post('http://localhost:8080/users/login', user).then((res)=>{
                if(res.data.token){
                    sessionStorage.setItem("isLogged", true);
                    navigate("/");
                } else {
                    alert("login failed");
                }
            }).catch((err)=>{
                console.log(err);
            })
        }
    }
    

React+Koa打包为Windows EXE方案

方案一:结合pkg打包完整应用(后端+前端静态资源)

  1. 打包React静态文件:在React项目根目录执行npm run build,生成build文件夹。
  2. 后端集成静态资源服务:
    • 安装koa-static:npm install koa-static
    • 修改server.js,添加静态资源中间件:
      const serve = require('koa-static');
      const path = require('path');
      // ...
      app.use(serve(path.join(__dirname, '../react-project/build'))); // 替换为你的React build文件夹路径
      
    这样启动后端后,访问http://localhost:8080就能直接打开React页面。
  3. 用pkg打包后端:
    • 在后端package.json中添加pkg配置:
      "pkg": {
          "scripts": "server.js",
          "assets": "../react-project/build/**/*", // 包含静态资源
          "targets": ["win"]
      }
      
    • 执行pkg .,生成Windows平台的exe文件,运行该文件即可启动后端并加载前端页面。

方案二:用Electron打包纯React应用

如果不需要后端嵌入,只想打包React前端为桌面应用:

  1. 安装Electron相关依赖:npm install electron electron-builder --save-dev
  2. 在项目根目录创建main.js(Electron主进程文件):
    const { app, BrowserWindow } = require('electron');
    const path = require('path');
    
    function createWindow() {
        const win = new BrowserWindow({
            width: 800,
            height: 600,
            webPreferences: {
                nodeIntegration: true
            }
        });
        win.loadFile(path.join(__dirname, 'build/index.html')); // 加载React打包后的index.html
    }
    
    app.whenReady().then(createWindow);
    
  3. 在package.json中添加脚本:
    "scripts": {
        "electron-start": "electron .",
        "electron-build": "electron-builder --win"
    }
    
  4. 执行npm run electron-build,生成Windows exe安装包。

内容的提问来源于stack exchange,提问作者shashika idushan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 01:06:30