使用Snowpack与React无法访问Express接口的问题求助
问题:Node.js集成Express+Snowpack+React应用中Axios无法请求Express接口
基于Node.js搭建了集成Express、Snowpack与React的Web应用,页面视图可正常加载,但无法通过axios请求指定的Express接口。请求中的接口URL指向服务器正确,去掉/api/test可正常打开视图,尝试过仅用/api/test或localhost地址,仍无法访问目标接口。目前无法访问路由中的/test与/api/test接口,仅前端视图相关的目录路由可用,怀疑Snowpack未使用Express路由,而是通过自身配置挂载目录提供视图,不确定根目录的app.js是否仍在运行服务器,希望得到问题排查方向或解决方法。
React组件代码
import React, { useState } from 'react'; import axios from 'axios'; // form component const MyForm = () => { // state variable that triggers component render/handles state and variables related to form const [formData, setFormData] = useState({ username: '', password: '' }); // function that handles when data in the form is changed const handleChange = (event) => { setFormData({ ...formData, [event.target.name]: event.target.value }); }; // function that handles when the form is submitted const handleSubmit = async (event) => { event.preventDefault(); console.log('Form submitted on client side:', formData); console.log("Attempting to send form data to server."); try { const response = await axios.post('http://10.0.0.121:8080/api/test', formData); console.log('Server response: ', response.data); } catch (error) { console.error('Error communicating with server: ', error); } setFormData({ username: '', password: '' }); }; // Html of the component return ( <form id="Lform" onSubmit={handleSubmit}> <table> <tr> <td><label id="Uname">Username</label></td> <td><input type="text" name="username" value={formData.username} onChange={handleChange} required/></td> </tr> <tr> <td><label id="Pword">Password</label></td> <td><input type="password" name="password" value={formData.password} onChange={handleChange} required/></td> </tr> </table> <button type="submit">Submit</button> </form> ); };
Express路由代码(router.js)
const express = require('express'); const cors = require('cors'); var path = require('path') const router = express.Router(); router.use(cors()); router.use(express.json()); router.get('/', function(req, res){ res.sendFile(path.join(__dirname, 'public', "index.html")); }); router.get('/index.js', function(req, res){ res.sendFile(path.join(__dirname,'index.js')); }); router.get('/src/*', (req, res) =>{ res.sendFile(path.join(__dirname, 'src', req.params[0])); }); router.post('/api/test', (req, res)=>{ const clientData = req.body; res.send("Communication with server successful: ", JSON.stringify(clientData)); }); router.get('/test', (req, res) =>{ res.sendFile(path.join(__dirname,'test.html')); }); router.use(express.static('public')); module.exports = router;
根目录app.js代码
var express = require('express'); var http = require('http'); const cors = require('cors'); // import mongoose later var app = express(); const routes = require('./router'); app.use(cors()); app.use('/', routes); app.use(express.json()); const server = http.createServer(app); const port = process.env.PORT ?? 443; server.listen(port); console.log("root directory is: " + __dirname) console.log(`server is on http://localhost:${port}`);
排查方向与解决方法
1. 端口不匹配问题(核心)
前端Axios请求用的是8080端口,但Express服务器默认监听443端口(app.js中port = process.env.PORT ?? 443),端口不一致导致请求无法到达Express服务:
- 方案一:修改app.js的监听端口为8080,和前端请求一致:
const port = process.env.PORT ?? 8080; - 方案二:修改前端请求地址为Express实际监听的端口,比如如果是443,请求地址改为
http://10.0.0.121:443/api/test(若配置了HTTPS则用https)。
2. Snowpack代理配置
Snowpack开发服务器默认单独运行(端口8080),此时前端请求Express服务会触发跨域,且Snowpack不会自动转发请求。需要在snowpack.config.js中添加代理规则:
module.exports = { proxy: { '/api': { target: 'http://localhost:443', // 替换为你的Express服务地址+端口 changeOrigin: true, }, '/test': { target: 'http://localhost:443', changeOrigin: true, } }, };
之后前端Axios改用相对路径请求:
const response = await axios.post('/api/test', formData);
3. Express中间件与路由修正
- 请求体解析顺序错误:app.js中
app.use(express.json())放在了路由之后,导致Express无法解析POST请求的JSON体,需调整顺序:app.use(cors()); app.use(express.json()); // 移到路由之前 app.use('/', routes); - res.send参数错误:router.js中
res.send不能传递多个参数,需修改为模板字符串:res.send(`Communication with server successful: ${JSON.stringify(clientData)}`); - 重复中间件:router.js中
router.use(express.json())可删除,因为app.js已配置全局的JSON解析中间件。
4. 确认服务运行状态
- 启动Express服务:确保
node app.js已正常运行,控制台输出server is on http://localhost:xxx。 - 开发环境运行方式:若同时使用Snowpack开发服务器和Express,需确保两个服务都在启动状态;若生产环境,需将Snowpack编译后的静态资源(默认
build目录)交给Express托管,替换router.js中的静态资源路由:router.use(express.static(path.join(__dirname, 'build')));
内容的提问来源于stack exchange,提问作者Whitewolf
相关产品推荐
相关产品推荐

