qiankun微前端跨域问题完美解决方案

qiankun微前端跨域问题完美解决方案

【免费下载链接】qiankun 📦 🚀 Blazing fast, simple and complete solution for micro frontends. 【免费下载链接】qiankun 项目地址: https://gitcode.com/gh_mirrors/qi/qiankun

你是否在使用qiankun构建微前端应用时,频繁遇到"Access-Control-Allow-Origin"错误?是否为不同技术栈的子应用跨域配置感到困惑?本文将从根本原因到实际解决方案,帮你彻底解决qiankun微前端架构中的跨域难题,让你轻松实现主应用与子应用的无缝通信。

读完本文后,你将掌握:

  • 微前端跨域问题的本质原因
  • 3种服务端跨域配置方案
  • 主应用与子应用的跨域代码配置
  • 开发环境与生产环境的不同处理策略
  • 常见跨域场景的解决方案

跨域问题的根源解析

在微前端架构中,主应用与子应用通常运行在不同的端口或域名下,当主应用通过qiankun加载子应用资源时,浏览器的同源策略会阻止这种跨域请求。qiankun通过fetch API获取子应用的静态资源,这使得跨域问题成为微前端实施过程中的常见障碍。

微前端跨域的三种常见场景

场景描述难度
静态资源跨域主应用加载子应用JS/CSS等资源★★☆☆☆
API请求跨域子应用请求后端接口★★★☆☆
Cookie携带跨域跨域请求中携带认证Cookie★★★★☆

官方文档中明确指出:"qiankun 将会通过 fetch 去获取微应用的引入的静态资源,所以必须要求这些静态资源支持跨域" docs/faq/README.zh-CN.md

服务端跨域解决方案

Nginx配置方案

最常用且推荐的跨域解决方案是在服务端配置CORS头,以Nginx为例:

location / {
  # 允许所有域名跨域访问
  add_header Access-Control-Allow-Origin *;
  # 允许特定域名跨域访问
  # add_header Access-Control-Allow-Origin https://main-app.com;
  add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
  add_header Access-Control-Allow-Headers Content-Type;
  
  # 对于预检请求直接返回204
  if ($request_method = 'OPTIONS') {
    return 204;
  }
}

特别地,对于子应用的HTML文件,建议配置不缓存,确保每次请求都能获取最新内容:

location = /index.html {
  add_header Cache-Control no-cache;
  add_header Access-Control-Allow-Origin *;
}

Node.js服务端配置

如果你的后端使用Node.js,可以通过以下方式配置CORS:

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

// 允许所有域名
app.use(cors());

// 或配置特定域名
app.use(cors({
  origin: 'https://main-app.com',
  credentials: true // 允许携带Cookie
}));

app.listen(3000);

主应用配置方案

Webpack开发环境配置

在开发环境中,可以通过Webpack的devServer配置跨域代理。主应用的webpack.config.js配置如下:

module.exports = {
  devServer: {
    port: 7099,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
    proxy: {
      // 代理子应用API请求
      '/api': {
        target: 'http://localhost:7101', // 子应用API地址
        changeOrigin: true,
        pathRewrite: {'^/api': ''}
      }
    }
  }
};

上述配置来自qiankun官方示例项目 examples/main/webpack.config.js,通过设置Access-Control-Allow-Origin: *允许所有域名访问主应用资源。

自定义fetch方法

qiankun允许通过自定义fetch方法来处理跨域请求,特别是需要携带Cookie的场景:

import { start } from 'qiankun';

start({
  async fetch(url, ...args) {
    // 对需要携带Cookie的请求特殊处理
    if (url.includes('/api/auth')) {
      return window.fetch(url, {
        ...args,
        credentials: 'include', // 允许跨域请求携带Cookie
      });
    }
    
    return window.fetch(url, ...args);
  },
});

子应用配置方案

Vue子应用配置

Vue子应用需要在vue.config.js中配置跨域相关设置:

module.exports = {
  devServer: {
    port: 7101,
    headers: {
      'Access-Control-Allow-Origin': '*',
    }
  },
  configureWebpack: {
    output: {
      // 把子应用打包成umd库格式
      library: `${name}-[name]`,
      libraryTarget: 'umd',
      jsonpFunction: `webpackJsonp_${name}`,
    },
  },
};

以上配置来自 examples/vue/vue.config.js,关键在于设置Access-Control-Allow-Origin: *和正确的打包格式。

React子应用配置

React子应用需要在webpack.config.js中进行类似配置:

module.exports = {
  devServer: {
    port: 7102,
    headers: {
      'Access-Control-Allow-Origin': '*',
    }
  },
  output: {
    library: name,
    libraryTarget: 'umd',
    jsonpFunction: `webpackJsonp_${name}`,
  },
};

上述配置来自 examples/react15/webpack.config.js,确保子应用资源能被主应用跨域访问。

publicPath配置

子应用的静态资源路径必须使用绝对路径,推荐使用运行时publicPath配置:

// 在子应用入口文件的顶部添加
if (window.__POWERED_BY_QIANKUN__) {
  // 动态设置publicPath
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

这种方式可以确保子应用资源始终从正确的路径加载,避免因路径问题导致的404错误。

常见问题解决方案

图片和字体文件跨域

由于qiankun会将外链样式转换为内联样式,导致图片和字体文件的相对路径失效。解决方案有两种:

  1. 使用CDN地址引用图片和字体文件
  2. 使用webpack的url-loader将小文件转为base64
// webpack配置
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif|webp|woff2?|eot|ttf|otf)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096, // 小于4kb的文件转为base64
            },
          },
        ],
      },
    ],
  },
};

多实例应用跨域

当同一子应用需要在页面中多次实例化时,需要清除webpack的chunk缓存:

function removeWebpackChunkCacheWhenAppHaveMultiInstance(appName) {
  const mountedSameNameApps = document.querySelectorAll(`[data-name^="${appName}"]`);
  if (mountedSameNameApps.length > 1) {
    mountedSameNameApps.forEach((appContainerElement) => {
      appContainerElement.querySelectorAll('script[src]').forEach((script) => {
        script.removeAttribute('data-webpack');
      });
    });
  }
}

这段代码来自qiankun源码 packages/qiankun/src/core/loadApp.ts,通过移除data-webpack属性来强制重新加载资源。

微应用间跳转跨域

微应用之间的页面跳转需要特别处理,推荐使用主应用提供的路由实例或history.pushState

// 微应用内部跳转
function navigateTo(path) {
  if (window.__POWERED_BY_QIANKUN__) {
    // 通过主应用提供的路由方法跳转
    window.mainAppRouter.push(path);
  } else {
    // 独立运行时使用自身路由
    router.push(path);
  }
}

跨域解决方案总结

qiankun微前端跨域问题的解决需要从多个层面入手:

  1. 服务端层面:配置CORS头,允许跨域请求
  2. 主应用层面:设置正确的响应头,配置代理,自定义fetch
  3. 子应用层面:配置webpack输出格式,设置publicPath
  4. 资源层面:使用CDN或base64处理静态资源

通过上述方案的组合应用,可以解决qiankun微前端架构中的几乎所有跨域场景。在实际项目中,建议根据具体情况选择最合适的方案,优先考虑服务端配置和开发环境代理,复杂场景下再使用自定义fetch方法。

最后,推荐参考qiankun官方文档的常见问题部分,获取更多关于跨域及其他问题的解决方案。

【免费下载链接】qiankun 📦 🚀 Blazing fast, simple and complete solution for micro frontends. 【免费下载链接】qiankun 项目地址: https://gitcode.com/gh_mirrors/qi/qiankun

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值