下面是一個完整的指南,教你如何從零開始構建一個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請求代理
- 開發與生產環境支持
- 安全增強
- 部署選項
你可以根據實際需求進一步定制和擴展這個基礎架構。