下面是一个完整的指南,教你如何从零开始构建一个Node.js服务来托管前端项目,并代理API请求到其他服务器。
1. 项目初始化
# 创建项目目录
mkdir node-proxy-server
cd node-proxy-server# 初始化npm项目
npm init -y# 安装必要依赖
npm install express http-proxy-middleware compression cors morgan
npm install nodemon --save-dev
2. 基础服务器配置
创建 server.js
文件:
const express = require('express')
const path = require('path')
const { createProxyMiddleware } = require('http-proxy-middleware')
const compression = require('compression')
const cors = require('cors')
const morgan = require('morgan')const app = express()
const PORT = process.env.PORT || 3000// 中间件配置
app.use(compression()) // 启用gzip压缩
app.use(cors()) // 跨域支持
app.use(morgan('dev')) // 请求日志// 静态文件服务 - 托管前端构建产物
app.use(express.static(path.join(__dirname, 'dist')))// API代理配置
const apiProxy = createProxyMiddleware({target: 'http://api.your-backend.com', // 你的后端API地址changeOrigin: true,pathRewrite: {'^/api': '' // 移除/api前缀},onProxyReq: (proxyReq, req, res) => {// 可以在这里添加请求头等操作console.log(`代理请求: ${req.method} ${req.path} -> ${proxyReq.path}`)},onError: (err, req, res) => {console.error('代理错误:', err)res.status(500).json({ error: '代理请求失败' })}
})// 应用代理中间件
app.use('/api', apiProxy)// 处理前端路由 - 所有未匹配的请求返回index.html
app.get('*', (req, res) => {res.sendFile(path.join(__dirname, 'dist', 'index.html'))
})// 启动服务器
app.listen(PORT, () => {console.log(`服务器运行在 http://localhost:${PORT}`)console.log(`代理API请求到: http://api.your-backend.com`)
})
3. 前端项目构建与部署
假设你有一个Vue/React前端项目:
- 构建前端项目:
# 在Vue项目中
npm run build# 或React项目中
npm run build
- 将构建产物复制到Node.js项目:
# 从Vue项目
cp -R your-vue-project/dist ./node-proxy-server/# 或从React项目
cp -R your-react-project/build ./node-proxy-server/dist
4. 环境变量配置
创建 .env
文件:
PORT=3000
API_BASE_URL=http://api.your-backend.com
NODE_ENV=production
修改 server.js
使用环境变量:
require('dotenv').config()// 更新代理配置
const apiProxy = createProxyMiddleware({target: process.env.API_BASE_URL || 'http://api.your-backend.com',// ...其他配置不变
})
5. 高级代理配置
多API端点代理
// 用户服务
app.use('/api/user', createProxyMiddleware({target: 'http://user-service.your-backend.com',changeOrigin: true,pathRewrite: { '^/api/user': '' }
}))// 订单服务
app.use('/api/order', createProxyMiddleware({target: 'http://order-service.your-backend.com',changeOrigin: true,pathRewrite: { '^/api/order': '' }
}))
WebSocket代理
const wsProxy = createProxyMiddleware('/ws', {target: 'ws://your-websocket-server.com',ws: true,changeOrigin: true,logLevel: 'debug'
})app.use(wsProxy)
6. 安全增强
const helmet = require('helmet')// 添加安全头
app.use(helmet())// 限制请求体大小
app.use(express.json({ limit: '10kb' }))
app.use(express.urlencoded({ extended: true, limit: '10kb' }))// 速率限制
const rateLimit = require('express-rate-limit')
const limiter = rateLimit({windowMs: 15 * 60 * 1000, // 15分钟max: 100 // 每个IP限制100个请求
})
app.use(limiter)
7. 开发与生产配置
package.json脚本
{"scripts": {"start": "node server.js","dev": "nodemon server.js","test": "echo \"Error: no test specified\" && exit 1"}
}
开发模式热重载
if (process.env.NODE_ENV === 'development') {const chokidar = require('chokidar')const watcher = chokidar.watch('./dist')watcher.on('ready', () => {watcher.on('all', () => {console.log('检测到前端文件变化,清除模块缓存...')Object.keys(require.cache).forEach(id => {if (id.includes('/dist/')) delete require.cache[id]})})})
}
8. 完整项目结构
node-proxy-server/
├── dist/ # 前端构建产物
│ ├── index.html
│ ├── static/
│ └── ...
├── server.js # 主服务器文件
├── .env # 环境变量
├── .gitignore
└── package.json
9. 部署指南
PM2生产环境部署
npm install pm2 -g
pm2 start server.js --name "node-proxy"
pm2 save
pm2 startup
Docker部署
创建 Dockerfile
:
FROM node:16-alpineWORKDIR /appCOPY package*.json ./
RUN npm install --productionCOPY . .ENV PORT=3000
ENV NODE_ENV=productionEXPOSE 3000CMD ["node", "server.js"]
构建并运行:
docker build -t node-proxy .
docker run -d -p 3000:3000 --name node-proxy node-proxy
10. 测试与验证
- 启动服务器:
npm run dev
-
验证静态文件服务:
访问http://localhost:3000
应该看到你的前端应用 -
验证API代理:
访问http://localhost:3000/api/some-endpoint
应该代理到你的后端服务 -
验证前端路由:
刷新非根路由(如http://localhost:3000/about
)应该正确返回index.html
常见问题解决
-
代理不工作:
- 检查目标服务器是否可访问
- 检查代理路径配置是否正确
- 查看服务器日志中的错误信息
-
前端路由问题:
- 确保所有路由都返回index.html
- 检查前端路由模式(history vs hash)
-
跨域问题:
- 确保正确配置了CORS中间件
- 检查代理是否正确地修改了Origin头
这个Node.js代理服务器提供了完整的解决方案,包括:
- 静态文件服务
- API请求代理
- 开发与生产环境支持
- 安全增强
- 部署选项
你可以根据实际需求进一步定制和扩展这个基础架构。