WebSocket URL 配置记录

1. 原始方案(静态配置)

// 依赖环境变量,需在 .env 文件中配置
const websocketUrl = import.meta.env.VITE_WEBSOCKET_SERVER_BASEURL;

缺点

  • 需要手动配置环境变量
  • 不灵活,切换环境需要修改配置
  • 开发和生产环境需要不同配置

2. 动态方案(推荐)

方案一:纯动态生成

/**
 * 动态生成 WebSocket URL
 * 基于当前页面协议和域名自动生成
 * @returns {string} WebSocket 连接地址
 */
const getWebSocketUrl = () => {
  const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
  const host = window.location.host;
  return `${protocol}//${host}/api/cs/chat/ws`;
};

// 使用
const websocketUrl = getWebSocketUrl();

优点

  • 完全自动,无需配置
  • 自动适应 https/wss
  • 与页面同源,避免跨域问题

适用场景

  • WebSocket 服务与网页同域名
  • 单域名部署
  • 开发环境

方案二:环境变量优先,动态生成兜底

/**
 * 获取 WebSocket URL
 * 优先使用环境变量,不存在时动态生成
 * @returns {string} WebSocket 连接地址
 */
const getWebSocketUrl = () => {
  // 1. 优先使用环境变量配置
  const envUrl = import.meta.env.VITE_WEBSOCKET_SERVER_BASEURL;
  if (envUrl && envUrl.trim() !== '') {
    return envUrl;
  }
  
  // 2. 动态生成(兜底方案)
  const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
  const host = window.location.host;
  return `${protocol}//${host}/api/cs/chat/ws`;
};

// 使用
const websocketUrl = getWebSocketUrl();

优点

  • 灵活性高,可覆盖各种场景
  • 支持环境特定配置
  • 有兜底方案,更健壮

方案三:带参数配置

/**
 * 获取 WebSocket URL
 * @param {Object} options 配置选项
 * @param {string} options.path WebSocket路径,默认 '/api/cs/chat/ws'
 * @param {string} options.customHost 自定义主机地址
 * @returns {string} WebSocket 连接地址
 */
const getWebSocketUrl = (options = {}) => {
  const { 
    path = '/api/cs/chat/ws',
    customHost = null 
  } = options;
  
  // 优先使用环境变量
  const envUrl = import.meta.env.VITE_WEBSOCKET_SERVER_BASEURL;
  if (envUrl && envUrl.trim() !== '') {
    return envUrl;
  }
  
  // 使用自定义主机或当前主机
  const host = customHost || window.location.host;
  const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
  
  return `${protocol}//${host}${path}`;
};

// 使用示例
const websocketUrl = getWebSocketUrl();  // 默认配置
// 或
const customWebSocketUrl = getWebSocketUrl({
  path: '/api/other/ws',
  customHost: 'api.example.com'
});

3. 环境变量配置示例

# .env.development (开发环境)
VITE_WEBSOCKET_SERVER_BASEURL=ws://localhost:3000/api/cs/chat/ws

# .env.production (生产环境)
VITE_WEBSOCKET_SERVER_BASEURL=wss://api.example.com/api/cs/chat/ws

# .env.test (测试环境)
VITE_WEBSOCKET_SERVER_BASEURL=ws://test-api.example.com/api/cs/chat/ws

4. WebSocket 连接示例

// 完整的 WebSocket 使用示例
class WebSocketService {
  constructor(options = {}) {
    this.url = getWebSocketUrl(options);
    this.socket = null;
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = 5;
  }
  
  connect() {
    try {
      this.socket = new WebSocket(this.url);
      this.setupEventListeners();
    } catch (error) {
      console.error('WebSocket 连接失败:', error);
      this.handleReconnect();
    }
  }
  
  setupEventListeners() {
    this.socket.onopen = (event) => {
      console.log('WebSocket 连接成功:', this.url);
      this.reconnectAttempts = 0;
    };
    
    this.socket.onmessage = (event) => {
      console.log('收到消息:', event.data);
    };
    
    this.socket.onclose = (event) => {
      console.log('WebSocket 连接关闭');
      this.handleReconnect();
    };
    
    this.socket.onerror = (error) => {
      console.error('WebSocket 错误:', error);
    };
  }
  
  handleReconnect() {
    if (this.reconnectAttempts < this.maxReconnectAttempts) {
      this.reconnectAttempts++;
      const delay = Math.min(1000 * 2 ** this.reconnectAttempts, 30000);
      
      console.log(`${delay}ms 后尝试重连,第 ${this.reconnectAttempts} 次`);
      
      setTimeout(() => {
        this.connect();
      }, delay);
    }
  }
  
  sendMessage(message) {
    if (this.socket?.readyState === WebSocket.OPEN) {
      this.socket.send(JSON.stringify(message));
    } else {
      console.error('WebSocket 未连接');
    }
  }
  
  disconnect() {
    if (this.socket) {
      this.socket.close();
      this.socket = null;
    }
  }
}

// 使用
const wsService = new WebSocketService();
wsService.connect();

5. 注意事项

跨域问题

  • 如果 WebSocket 服务在不同域名下,需要服务端配置 CORS
  • 同源策略对 WebSocket 较为宽松,但仍需注意

协议匹配

  • HTTP 对应 WS (ws://)
  • HTTPS 对应 WSS (wss://)
  • 混合内容可能被浏览器阻止

路径配置

  • 确保路径与服务端配置一致
  • 注意结尾斜杠

网络环境

  • 代理服务器可能需要特殊配置
  • 防火墙可能阻止 WebSocket 连接
  • 移动网络可能对长连接有限制

6. 最佳实践建议

  1. 开发环境:使用方案一(纯动态),简化配置
  2. 生产环境:使用方案二(环境变量优先),便于管理
  3. 多环境部署:配合 CI/CD 自动注入环境变量
  4. 错误处理:添加连接失败的重试机制
  5. 监控:记录连接状态和错误日志

7. 兼容性处理

// 添加兼容性检查
const isWebSocketSupported = () => {
  return 'WebSocket' in window || 'MozWebSocket' in window;
};

if (!isWebSocketSupported()) {
  console.warn('浏览器不支持 WebSocket,考虑使用轮询或 SSE 作为备选方案');
}
posted @ 2026-05-09 15:05  栖木hy  阅读(31)  评论(0)    收藏  举报