从零搭建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加密:- 安装依赖:
npm install bcrypt - 注册用户时加密密码:
const hashedPassword = await bcrypt.hash(password, 10);,存储hashedPassword而非明文 - 登录时校验:
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打包完整应用(后端+前端静态资源)
- 打包React静态文件:在React项目根目录执行
npm run build,生成build文件夹。 - 后端集成静态资源服务:
- 安装
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页面。 - 安装
- 用pkg打包后端:
- 在后端
package.json中添加pkg配置:"pkg": { "scripts": "server.js", "assets": "../react-project/build/**/*", // 包含静态资源 "targets": ["win"] } - 执行
pkg .,生成Windows平台的exe文件,运行该文件即可启动后端并加载前端页面。
- 在后端
方案二:用Electron打包纯React应用
如果不需要后端嵌入,只想打包React前端为桌面应用:
- 安装Electron相关依赖:
npm install electron electron-builder --save-dev - 在项目根目录创建
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); - 在
package.json中添加脚本:"scripts": { "electron-start": "electron .", "electron-build": "electron-builder --win" } - 执行
npm run electron-build,生成Windows exe安装包。
内容的提问来源于stack exchange,提问作者shashika idushan
相关产品推荐
相关产品推荐

