跳到主要内容

前端跨域解决方案

在前端开发过程中,跨域(CORS)是一个常见问题。本文档介绍使用 Lovrabet CLI 创建的项目中,如何解决跨域问题的多种方案。

什么是跨域问题?

跨域是指浏览器出于安全考虑,限制从一个域名的网页去请求另一个域名的资源。当协议、域名或端口不同时,就会产生跨域问题。

重要说明:即使都是 *.lovrabet.com 的子域名,dev.lovrabet.comapi.lovrabet.com 仍然是不同的域名,属于跨域请求。只是通过配置 CORS 白名单,允许了这种跨域访问。

跨域判断标准

浏览器判断是否跨域,主要看以下三个要素是否完全相同:

  • 协议(Protocol):http vs https
  • 域名(Domain):dev.lovrabet.com vs api.lovrabet.com
  • 端口(Port):80 vs 443 vs 3000

跨域示例

前端地址API 地址是否跨域说明
http://localhost:3000https://api.lovrabet.com跨域协议、域名、端口都不同
https://dev.lovrabet.comhttps://api.lovrabet.com跨域域名不同(虽然都是 lovrabet.com 子域)
https://dev.lovrabet.comhttps://dev.lovrabet.com同域完全相同的域名
http://example.com:80http://example.com:443跨域端口不同
https://example.comhttp://example.com跨域协议不同

注意dev.lovrabet.comapi.lovrabet.com 虽然都是 lovrabet.com 的子域名,但仍然是跨域。只是通过服务器端配置 CORS 白名单,允许了这种跨域访问,所以不会出现跨域错误。

解决方案概览

Lovrabet CLI 提供了多种解决跨域问题的方案,你可以根据实际场景选择:

方案适用场景优点缺点
方案1:使用 dev.lovrabet.com开发阶段自动配置,无需额外设置仅限开发环境
方案2:服务器 CORS 配置需要访问自有 API简单直接需要服务器权限
方案3:服务器转发复杂业务场景灵活可控,可添加业务逻辑需要额外开发
方案4:独立部署生产环境完全自主,无跨域问题需要部署资源

方案 1:使用 dev.lovrabet.com 开发域名(推荐)

工作原理

使用 lovrabet start 启动项目时,CLI 会自动将你的本地项目映射到 dev.lovrabet.com 开发域名。

重要dev.lovrabet.comapi.lovrabet.com 虽然都是 lovrabet.com 的子域名,但仍然是不同的域名,属于跨域请求。只是 dev.lovrabet.com 已经加入了 Lovrabet 平台的 CORS 白名单,服务器端允许了来自 dev.lovrabet.com 的跨域请求,所以不会出现跨域错误。

使用方法

# 启动开发服务器
lovrabet start

# 访问地址会自动映射到
# https://dev.lovrabet.com/your-app-path

优势

  • 零配置:无需任何额外设置,开箱即用
  • 自动映射:CLI 自动处理域名映射和 HTTPS
  • 白名单已配置dev.lovrabet.com 已加入跨域白名单
  • 开发友好:支持热更新,开发体验流畅

注意事项

  • 此方案仅适用于开发环境
  • 需要登录 Lovrabet 平台才能使用 dev.lovrabet.com 域名
  • 如果访问非 *.lovrabet.com 的 API,仍可能出现跨域问题

方案 2:服务器 CORS 配置

适用场景

当你的前端应用运行在 dev.lovrabet.com,但需要访问自己服务器的 API 时,可能遇到跨域问题。此时可以在自己的服务器上配置 CORS,允许 dev.lovrabet.com 访问。

配置示例

Node.js (Express)

const express = require('express');
const app = express();

// 允许 dev.lovrabet.com 跨域访问
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://dev.lovrabet.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Credentials', 'true');

if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});

Nginx

server {
listen 80;
server_name your-api-domain.com;

location / {
# 允许 dev.lovrabet.com 跨域访问
add_header 'Access-Control-Allow-Origin' 'https://dev.lovrabet.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
add_header 'Access-Control-Allow-Credentials' 'true';

if ($request_method = 'OPTIONS') {
return 204;
}

# 你的 API 处理逻辑
proxy_pass http://backend;
}
}

Spring Boot (Java)

@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("https://dev.lovrabet.com")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
};
}
}

优势

  • 简单直接:只需在服务器端配置一次
  • 性能好:浏览器直接访问 API,无中间层
  • 灵活:可以精确控制允许的域名和方法

注意事项

  • 需要服务器管理员权限
  • 生产环境建议使用环境变量配置允许的域名
  • 注意安全性,不要使用通配符 * 允许所有域名

方案 3:服务器转发请求(API 中转)

适用场景

当无法修改服务器 CORS 配置,或者需要在请求中添加业务逻辑、权限验证、数据转换时,可以使用服务器转发方案。

工作原理

前端不直接调用目标 API,而是调用自己的服务器接口,由服务器转发请求到目标 API。这样可以:

  • 绕过浏览器的跨域限制
  • 在服务器端添加业务逻辑
  • 隐藏 API 实现细节
  • 统一错误处理和日志记录

实现示例

参考 Next.js 演示项目 中的场景 3:API 中转方案。

Next.js API Route 示例

// app/api/proxy/data/route.ts
import { NextRequest, NextResponse } from "next/server";
import { createServerClient } from "@/lib/sdk-client";

export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams;
const page = searchParams.get("page") || "1";
const size = searchParams.get("size") || "10";

// 在服务器端创建客户端(无跨域问题)
const client = createServerClient();
const model = client.getModel(0);

// 调用 SDK 获取数据
const response = await model.filter({
page: parseInt(page),
pageSize: parseInt(size),
});

// 返回数据给前端
return NextResponse.json({
success: true,
data: response,
});
} catch (error) {
return NextResponse.json(
{
success: false,
error: error instanceof Error ? error.message : "Unknown error",
},
{ status: 500 }
);
}
}

前端调用

// 前端通过自己的 API 路由获取数据
const fetchData = async () => {
const response = await fetch('/api/proxy/data?page=1&size=10');
const result = await response.json();

if (result.success) {
// 使用数据
console.log(result.data);
}
};

Express.js 示例

const express = require('express');
const axios = require('axios');
const app = express();

app.use(express.json());

// 代理 API 请求
app.get('/api/proxy/data', async (req, res) => {
try {
const { page, size } = req.query;

// 在服务器端调用目标 API(无跨域限制)
const response = await axios.get('https://api.target.com/data', {
params: { page, size },
headers: {
'Authorization': `Bearer ${process.env.API_TOKEN}`,
},
});

// 可以在这里添加业务逻辑、数据转换等
const transformedData = transformData(response.data);

res.json({
success: true,
data: transformedData,
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message,
});
}
});

function transformData(data) {
// 数据转换逻辑
return data;
}

优势

  • 完全绕过跨域:服务器端无跨域限制
  • 灵活可控:可以添加业务逻辑、权限验证
  • 隐藏实现:前端不需要知道目标 API 的细节
  • 统一处理:可以统一错误处理、日志记录、缓存等

注意事项

  • 需要额外的服务器资源
  • 增加了请求链路,可能有轻微延迟
  • 需要处理服务器端的错误和超时

完整示例

查看完整的实现示例:openapi-nextjs-demo 项目中的 scenario3-proxy 场景。


方案 4:独立部署到自己的服务器

适用场景

开发完成后,将项目独立部署到自己的服务器,使用自己的域名。这样就不会有跨域问题,因为前端和 API 都在你的控制范围内。

部署步骤

1. 构建生产版本

# 构建项目
lovrabet build

# 构建产物在 dist/ 目录

2. 部署到服务器

dist/ 目录的内容部署到你的 Web 服务器(Nginx、Apache、CDN 等)。

3. 配置域名和 HTTPS

# Nginx 配置示例
server {
listen 80;
server_name your-domain.com;

# 重定向到 HTTPS
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl;
server_name your-domain.com;

ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;

root /path/to/dist;
index index.html;

location / {
try_files $uri $uri/ /index.html;
}
}

4. 配置 API 地址

在项目配置中设置生产环境的 API 地址:

// .env.production
VITE_API_BASE_URL=https://api.your-domain.com

优势

  • 完全自主:完全控制前端和 API
  • 无跨域问题:同域名或已配置 CORS
  • 性能最优:直接访问,无中间层
  • 生产就绪:适合生产环境使用

注意事项

  • 需要服务器资源和域名
  • 需要配置 HTTPS 证书
  • 需要处理路由和静态资源
  • 建议使用 CDN 加速静态资源

方案选择建议

根据你的实际场景选择合适的方案:

开发阶段推荐方案说明
本地开发方案 1:dev.lovrabet.com零配置,开箱即用
需要访问自有 API方案 2:服务器 CORS简单直接,性能好
复杂业务场景方案 3:服务器转发灵活可控,功能强大
生产环境方案 4:独立部署完全自主,性能最优

常见问题

Q: 为什么使用 dev.lovrabet.com 不会跨域?

A: 实际上 dev.lovrabet.comapi.lovrabet.com 仍然是跨域(因为域名不同)。但 dev.lovrabet.com 已经加入了 Lovrabet 平台的 CORS 白名单,服务器端配置了允许来自 dev.lovrabet.com 的跨域请求,所以浏览器不会阻止这些请求,看起来就像没有跨域问题一样。

Q: 可以在本地 localhost 开发吗?

A: 可以,但 localhost 不在跨域白名单中,访问 *.lovrabet.com 的 API 会出现跨域问题。建议使用 dev.lovrabet.com 进行开发。

Q: 生产环境必须独立部署吗?

A: 不一定。如果你的前端和 API 都在同一域名下,或者已经配置了 CORS,也可以直接部署。但独立部署通常更灵活、更安全。

Q: 服务器转发会影响性能吗?

A: 会有轻微影响,因为增加了请求链路。但对于大多数应用来说,这个影响可以忽略不计。如果对性能要求极高,建议使用方案 2 或方案 4。

相关资源