前端跨域解决方案

126 阅读1分钟

跨子域(二级域名不同)

  1. document.domain + iframe

    • 在父子页面中设置相同的 document.domain,使其成为同一域,实现跨域访问。
    // 父页面
    document.domain = "example.com";
    
    // 子页面
    document.domain = "example.com";
    
  2. postMessage

    • 在不同窗口或 iframe 之间通过 postMessage 安全传递数据。
    // 发送消息
    window.parent.postMessage('Hello from iframe!', 'https://example.com');
    
    // 接收消息
    window.addEventListener('message', (event) => {
      // 处理接收到的消息
      console.log(event.data);
    });
    

跨主域(域名不同)

  1. JSONP:

    • 利用动态创建 <script> 标签,通过回调函数获取跨域数据。
    function handleJSONP(response) {
      // 处理获取到的数据
      console.log(response);
    }
    
    const script = document.createElement('script');
    script.src = 'https://api.example.com/data?callback=handleJSONP';
    document.head.appendChild(script);
    
  2. CORS(Cross-Origin Resource Sharing):

    • 在服务器响应头中添加 CORS 头,允许特定域访问资源。
    Access-Control-Allow-Origin: *
    
  3. 代理代理:

    • 在服务器端设置代理,将前端请求转发到目标服务器。
  4. Nginx反向代理:

    • 使用 Nginx 配置反向代理,将请求代理到目标服务器。
  5. 接口代理本地模拟:

    • 在开发环境中,通过代理请求本地模拟数据。
  6. 按环境代理接口:

    • 针对不同环境配置不同的代理规则,如开发、测试、生产环境。
  7. Browsersync代理本地服务:

    • 使用 Browsersync 进行开发时本地服务的代理。
  8. WebSocket跨域:

    • WebSocket 不受同源策略限制,可用于双向通信。
    // 创建 WebSocket 连接
    const socket = new WebSocket('wss://example.com/socket');
    
    // 监听连接打开事件
    socket.addEventListener('open', (event) => {
      // 连接已打开
    });
    
    // 监听消息事件
    socket.addEventListener('message', (event) => {
      // 处理接收到的消息
      console.log(event.data);
    });
    
    // 监听连接关闭事件
    socket.addEventListener('close', (event) => {
      // 连接已关闭
    });
    
    // 发送消息
    socket.send('Hello, server!');
    
  9. 前后端配置Origin检查:

    • 后端配置允许指定来源的请求,通过检查 Origin 头。
    // Node.js Express 服务器配置
    const express = require('express');
    const app = express();
    
    app.use((req, res, next) => {
      res.header('Access-Control-Allow-Origin', 'https://example.com');
      res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
      res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
      next();
    });
    
    // 其他路由和中间件配置
    

测试环境跨域

  1. webpack-dev-server代理:

    • 使用 webpack-dev-server 的代理功能。
    // webpack.config.js
    module.exports = {
      devServer: {
        proxy: {
          '/api': 'http://localhost:3000', // 代理到本地服务
        },
      },
    };
    
  2. hosts域名指向:

    • 在开发环境修改 hosts 文件,将域名指向本地。
    // hosts 文件
    127.0.0.1   example.dev
    

模块打包跨域

  1. 外部模块CDN引入:

    • 将一些不常变动的模块引入自外部 CDN,减少跨域问题。
    <!-- 引入外部库,如 jQuery -->
    <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
    
  2. webpack externals:

    • 使用 webpack 的 externals 配置,将模块排除在打包范围外。
    // webpack.config.js
    module.exports = {
      externals: {
        jquery: 'jQuery', // 将 jQuery 排除在打包范围外
      },
    };
    

跨域资源加载

  1. CORS解决字体/图片跨域:

    • 在服务器端添加相应的 CORS 头,解决字体和图片跨域问题。
    # 服务器响应头
    Access-Control-Allow-Origin: *
    
  2. base64编码资源内联:

    • 将小体积的图片、字体等资源通过 base64 编码嵌入页面,避免跨域请求。
    /* CSS 中使用 base64 编码的图片 */
    .background {
      background: url(data:image/png;base64,iVBORw0KG...);
    }
    

这些详细示例涵盖了不同层面和环境下的前端跨域问题及解决方式。在实际开发中,根据具体需求选择合适的方法,并确保实施时考虑到安全性、性能和可维护性。