源码跨域资源适配逻辑?

访客 源码剖析 1

本文目录导读:

  1. 开发时适配(Dev Server)
  2. 构建时适配(Build Config)
  3. 运行时适配(Runtime Logic)
  4. 特殊资源适配逻辑
  5. 典型的“适配流程图”

“源码跨域资源适配逻辑”通常指在前端项目源码(或构建产物) 中,处理不同域名(或端口、协议)下资源(API、图片、字体、iframe、脚本等)请求时的配置与运行时逻辑。

这个适配逻辑的核心目标是:在开发和线上不同环境、不同域名部署时,保证前端代码能正确请求到后端资源,且不被浏览器同源策略拦截。

下面从开发时适配构建时适配运行时适配三个层面,以及常见的适配方案来拆解。


开发时适配(Dev Server)

在本地开发(localhost:3000)时,前端请求后端 API(api.example.com:8080)一定会产生跨域,适配逻辑通常包括:

  1. Proxy 代理(最常用)

    • 逻辑: 在 Webpack/Vite 的 devServer 中配置 proxy。
    • 原理: 浏览器请求 /api/user -> 开发服务器接收 -> 开发服务器转发http://api.example.com:8080/api/user -> 返回结果给浏览器。
    • 优势: 浏览器感觉是同源请求,无需服务端配置 CORS,开发体验最好。
    // vite.config.js (Vite 配置)
    export default defineConfig({
      server: {
        proxy: {
          '/api': {
            target: 'http://api.example.com:8080',
            changeOrigin: true, 
            // 适配路径:是否重写 /api/user -> /user
            rewrite: (path) => path.replace(/^\/api/, '')
          }
        }
      }
    })
  2. 本地 Mock 数据

    • 逻辑: 不依赖真实后端,本地拦截请求返回假数据。
    • 工具: Mock.js, MSW (Mock Service Worker)。

构建时适配(Build Config)

源码打包后部署到线上(www.myapp.com),请求生产 API(api.myapp.com)。

  1. 环境变量注入

    • 逻辑: 源码中不写死 API 地址,而是通过环境变量(.env 文件)读取。
    • 适配点: 构建时根据 NODE_ENV 或自定义变量替换为对应的域名。
    // .env.production
    VITE_API_BASE_URL = 'https://api.myapp.com'
    // .env.development
    VITE_API_BASE_URL = '/api'  // 开发时用proxy
    // 源码中使用
    const response = await fetch(`${import.meta.env.VITE_API_BASE_URL}/user`)
  2. 构建路径适配 (PublicPath)

    • 如果静态资源(JS/CSS/字体)部署在 CDN(cdn.myapp.com),而 HTML 在 www.myapp.com,需要设置 publicPath 为绝对路径(CDN 域名)或相对路径,这属于资源的跨域引用。

运行时适配(Runtime Logic)

这是“适配逻辑”中最核心的技术部分,指代码在浏览器中运行时如何处理跨域。

CORS(服务端配合)

  • 逻辑: 浏览器发现跨域请求后,检查响应头,若服务端未返回允许的头部,则拦截。
  • 适配方式: 前端无法独立解决,必须让后端添加响应头。
    • Access-Control-Allow-Origin: https://www.myapp.com (指定域名)
    • Access-Control-Allow-Methods: GET, POST, PUT
    • Access-Control-Allow-Headers: Content-Type, Authorization
    • Access-Control-Allow-Credentials: true (如果需要带着 Cookie)

JSONP(GET 请求适配)

  • 逻辑: <script> 标签不受同源策略限制,利用 src 请求带回调,服务端返回 callback(data)
  • 适用场景: 旧系统适配、仅 GET 请求、无需 Cookie。
    function jsonp(url, callbackName) {
       return new Promise((resolve, reject) => {
          window[callbackName] = (data) => resolve(data);
          const script = document.createElement('script');
          script.src = `${url}?callback=${callbackName}`;
          document.body.appendChild(script);
       });
    }
    // 请求 https://api.other.com/data
    jsonp('https://api.other.com/data', 'mycallback').then(data => ...)

WebSocket(无同源策略)

  • 逻辑: WebSocket 协议不受同源策略限制。
  • 适配: 直接连接即可。new WebSocket('wss://api.other.com/ws')

postMessage + iframe(跨域通信)

  • 场景: 嵌入第三方页面(如地图、支付页面),需要与父页面通信。

  • 逻辑: 父窗口 iframe.contentWindow.postMessage(data, targetOrigin),子窗口监听 message 事件。

    // 父窗口 (https://www.myapp.com)
    const iframe = document.getElementById('other-domain-iframe');
    iframe.contentWindow.postMessage({ action: 'getUserInfo' }, 'https://www.other.com');
    // 子窗口 (https://www.other.com)
    window.addEventListener('message', (event) => {
        if (event.origin === 'https://www.myapp.com') { // 适配:检查来源
            event.source.postMessage({ result: 'some data' }, event.origin);
        }
    });

特殊资源适配逻辑

除了 API,源码中的其他静态资源也有跨域问题:

  1. 图片 / 字体(CORS 属性)

    • 逻辑: 浏览器对 <img>@font-face 的跨域请求有特殊处理,特别是字体默认限制跨域。

    • 适配:

      • <img> 上添加 crossorigin="anonymous"(用于 Canvas 绘图时)。
      • 字体文件必须由服务器返回 Access-Control-Allow-Origin 头部。
      <img src="https://cdn.other.com/logo.png" crossorigin="anonymous" />
  2. Script 标签(CDN 资源)

    • 逻辑: script 默认不受同源策略限制,但无法捕获错误细节(如文件内部报错的行号)。

    • 适配:

      • <script> 上添加 crossorigin 属性(需要服务端配合返回 CORS 头)。
      • window.onerror 才能捕获到详细错误信息。
      <script src="https://cdn.other.com/sdk.js" crossorigin="anonymous"></script>

典型的“适配流程图”

假设你有一个 React/Vue 应用:

  1. 源码编写时: 所有请求基地址写入配置文件 config.js,读取 VITE_API_BASE_URL
  2. 本地开发 (npm run dev):
    • .env.developmentVITE_API_BASE_URL = ''/proxy-api
    • Vite/Webpack 的 Proxy 将 /proxy-api 转发到 http://192.168.1.100:8080
    • 适配结果: 无跨域问题。
  3. 构建打包 (npm run build):
    • 读取 .env.production 中的 VITE_API_BASE_URL = 'https://api.myapp.com'
    • 打包后的 JS 中写死 https://api.myapp.com
  4. 线上运行时:
    • 浏览器 www.myapp.com 的 JS 发起请求到 https://api.myapp.com/user
    • 若后端 Nginx/Node 配置了 CORS: 返回 Access-Control-Allow-Origin: https://www.myapp.com,请求成功。
    • 若后端未配置 CORS: 请求失败(浏览器拦截)。
  5. 错误处理与降级(适配逻辑的最后一层):
    • 源码中需有 try-catch 或 axios 拦截器,若检测到跨域错误(network error),可尝试降级方案(如通过自己的 BFF 层转发,或使用 JSONP 探测备用接口)。

“源码跨域资源适配逻辑”不是一个单一函数,而是一套贯穿开发、构建、运行三个阶段的策略组合

  • 开发期Proxy 适配(让你在 localhost 开发无感)。
  • 构建期环境变量 适配(让不同环境拿到不同的 API 域名)。
  • 运行期CORS / JSONP / postMessage / WebSocket 适配(浏览器与不同域资源的实际通信)。

标签: 跨域资源

抱歉,评论功能暂时关闭!