在 Node.js 項目中托管 React 打包后的靜態資源時,可能會遇到跨域問題(CORS)。以下是幾種解決方案:
1. 使用 Express 中間件設置 CORS 頭
const express = require('express');
const path = require('path');
const app = express();// 靜態資源目錄
app.use(express.static(path.join(__dirname, 'build')));// 設置 CORS 頭
app.use((req, res, next) => {res.header('Access-Control-Allow-Origin', '*');res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');next();
});// 處理 React 路由
app.get('*', (req, res) => {res.sendFile(path.join(__dirname, 'build', 'index.html'));
});const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {console.log(`Server is running on port ${PORT}`);
});
2. 使用 cors
中間件(推薦)
npm install cors
const express = require('express');
const cors = require('cors');
const path = require('path');
const app = express();// 使用 cors 中間件
app.use(cors()); // 允許所有來源// 或者更精確的控制
/*
app.use(cors({origin: ['http://your-frontend-domain.com', 'http://localhost:3000'],methods: ['GET', 'POST', 'PUT', 'DELETE'],allowedHeaders: ['Content-Type', 'Authorization']
}));
*/// 靜態資源目錄
app.use(express.static(path.join(__dirname, 'build')));// 處理 React 路由
app.get('*', (req, res) => {res.sendFile(path.join(__dirname, 'build', 'index.html'));
});const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {console.log(`Server is running on port ${PORT}`);
});
3. 代理服務器方案(適用于 API 請求)
如果前端需要訪問其他域的后端 API,可以設置代理:
const { createProxyMiddleware } = require('http-proxy-middleware');// 在 Express 中設置代理
app.use('/api', createProxyMiddleware({target: 'http://your-api-server.com',changeOrigin: true,pathRewrite: {'^/api': ''}
}));
4. 配置 React 的代理(開發環境)
在開發環境中,可以在 package.json
中配置代理:
{"proxy": "http://localhost:3001"
}
或者在 src/setupProxy.js
中配置:
const { createProxyMiddleware } = require('http-proxy-middleware');module.exports = function(app) {app.use('/api',createProxyMiddleware({target: 'http://localhost:3001',changeOrigin: true,}));
};
5. Nginx 反向代理配置(生產環境)
如果你使用 Nginx 作為前端服務器,可以這樣配置:
server {listen 80;server_name your-domain.com;location / {root /path/to/react/build;try_files $uri /index.html;}location /api {proxy_pass http://your-node-server:3000;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;# CORS 設置add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';}
}
6. 處理預檢請求 (OPTIONS)
app.options('*', cors()); // 處理所有 OPTIONS 請求
注意事項
- 生產環境中不要使用
Access-Control-Allow-Origin: '*'
,應該指定具體的域名 - 對于需要憑證的請求(如 cookies),需要設置
Access-Control-Allow-Credentials: true
- 確保響應頭中包含請求中發送的自定義頭
- 如果使用 HTTPS,確保所有資源也都是 HTTPS,避免混合內容問題
以上方法可以根據你的具體需求組合使用,通常在生產環境中推薦使用 Nginx 反向代理或精確配置的 CORS 中間件方案。