解决 Node.js 托管 React 静态资源的跨域问题

在 Node.js 项目中托管 React 打包后的静态资源时,可能会遇到跨域问题(CORS)。以下是几种解决方案:

1. 使用 Express 中间件设置 CORS 头

javascript 复制代码
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 中间件(推荐)

bash 复制代码
npm install cors
javascript 复制代码
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,可以设置代理:

javascript 复制代码
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 中配置代理:

json 复制代码
{
  "proxy": "http://localhost:3001"
}

或者在 src/setupProxy.js 中配置:

javascript 复制代码
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://localhost:3001',
      changeOrigin: true,
    })
  );
};

5. Nginx 反向代理配置(生产环境)

如果你使用 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)

javascript 复制代码
app.options('*', cors()); // 处理所有 OPTIONS 请求

注意事项

  1. 生产环境中不要使用 Access-Control-Allow-Origin: '*',应该指定具体的域名
  2. 对于需要凭证的请求(如 cookies),需要设置 Access-Control-Allow-Credentials: true
  3. 确保响应头中包含请求中发送的自定义头
  4. 如果使用 HTTPS,确保所有资源也都是 HTTPS,避免混合内容问题

以上方法可以根据你的具体需求组合使用,通常在生产环境中推荐使用 Nginx 反向代理或精确配置的 CORS 中间件方案。

相关推荐
ZC跨境爬虫9 分钟前
跟着 MDN 学 HTML day_38:(DocumentFragment 文档片段接口详解)
前端·javascript·ui·html·音视频
@大迁世界1 小时前
41.ShadCN 是什么?它如何和 Tailwind CSS 集成,从而更容易构建可访问且可自定义的 React 组件?
前端·javascript·css·react.js·前端框架
千叶风行2 小时前
Text-to-SQL 技术设计与注意事项
前端·人工智能·后端
软件开发技术深度爱好者2 小时前
HTML5+JavaScript读取DOCX 文档完整内容
前端·html5
幽络源小助理2 小时前
苹果CMS V10 MXPro V4.5模版下载, 自适应视频主题源码, 幽络源源码
前端·开源·源码·php源码
kyriewen3 小时前
坏了,黑客学会用AI写外挂了
前端·程序员·ai编程
xiangxiongfly9153 小时前
Vue3 根据角色权限动态加载路由
前端·javascript·vue.js·动态加载路由
达达尼昂3 小时前
Claude 多 Agent 系统:从零搭建一个 4 Agent 团队
前端·架构·ai编程
费曼学习法4 小时前
React 18 并发模式(Concurrent Mode):Fiber 架构的终极进化
javascript·react.js
容智信息4 小时前
AI Agent(智能体)的输出格式应该从 Markdown 转向 HTML吗?
前端·人工智能·rust·编辑器·html·prompt