qiankun子应用静态资源请求报错

337 阅读2分钟

项目技术栈:

主项目react+webpack;子项目vue3+vite;微前端框架为qiankun。然后由于qiankun不支持vite,用到了vite-plugin-qiankun这个插件。

插件的GitHub地址如下:

github.com/tengmaoqing…

静态资源的请求:

错误原因:

原项目中是使用import来引入图片资源,然后:src来动态加载资源,经过实验发现src是基于项目启动服务器的根目录的,比如主应用在localhost:3001,子应用跑在localhost:3200。

打开F12,点击网络,找到该图片,发现这个子应用图片的路径就是localhost:3001/xxx,

但是由于子应用跑在localhost:3200,所以图片的所在的路径应该是localhost:3200/xxx。

破案!!!

不过,我用import引入的js文件就不会出现问题,初步推测是由于用的插件的问题,然后我在插件作者的issue里面也找到了这个问题,但是还没有进行验证,后面如果有时间会验证一下。

解决方案:

1.图床:

这应该是最简单最方便的解决方案。

但是由于我公司没有自己的图床,所以不得不舍近求远。

2.写死:

直接把src改成http://localhost:3200/xxx,如图

image.png

但是由于一个项目可能要在不同的环境上部署,那这样的话部署前都需要改一下url,非常麻烦,而且写死,非常非常非常不优雅!!

3.base配置:

由于域名部分在开发环境中不会被使用,所以这个方法无法解决开发环境的问题。

image.png

4.转为base64编码:

由于我这个项目图片都比较小,转为base64编码还可以减少一些请求(资源被内联),减少一些服务器的压力。 简直一_二_。这是我目前找到的最优解。

Vite有一个assetsInlineLimit配置,但是是只适用于构建的,在本地dev调试起来还是不行,非常的不方便。 所以我便动手自己用node写了一个转为base64编码的vite插件。

函数如下:

import fs from 'fs';
import path from 'path';
import { transformSync } from 'esbuild'; // 使用 esbuild 来生成 sourcemap

export const base64SetPlugin = (limit = 100000000) => {
  // 缓存加载过的图片
  const cache = new Map();

  return {
    name: 'base64-set-plugin',
    // 内置的transform函数
    async transform(_: any, id: string) {
      try {
        // 只处理图片文件
        if (!/.(png|jpg|svg)$/.test(id)) return;

        // 缓存检查
        if (cache.has(id)) {
          return { code: cache.get(id) };
        }

        // 解析文件路径
        const filePath = path.resolve(id);
        const stat = await fs.promises.stat(filePath);

        // 文件大小检查
        if (stat.size > limit) return;

        // 读取文件并转换为 Base64
        const buffer = await fs.promises.readFile(filePath);
        const base64 = buffer.toString('base64');

        // 生成 Data URL
        const ext = path.extname(id).slice(1);
        const mimeType = ext === 'svg' ? 'image/svg+xml' : `image/${ext}`; //获得文件的扩展名
        const dataUrl = `data:${mimeType};base64,${base64}`;

        // 此处是为了生成sourcemap 如果不加,打包的时候会由于建立不了开发生产环境的桥梁而出现警告
        const result = transformSync(`export default ${JSON.stringify(dataUrl)}`, {
          sourcemap: true, // 开启 sourcemap 生成
          loader: 'js', // 处理为 JavaScript 代码
        });

        // 缓存转换后的代码和 sourcemap
        cache.set(id, result.code);

        // 返回带有 sourcemap 的代码
        return {
          code: result.code,
          map: result.map, // 返回 sourcemap
        };
      } catch (error) {
        console.error(`错误转换:   ${id}:`, error);
        return null;
      }
    },
  };
};

 vite.config.ts文件如下:

import { defineConfig, loadEnv } from 'vite';
import { setupVitePlugins } from './build';
import qiankun from 'vite-plugin-qiankun';
import { base64SetPlugin } from './src/utils/base64';

export default defineConfig((configEnv) => {

  return {
    plugins: [
      setupVitePlugins(viteEnv),
      qiankun('vueApp', {
        useDevMode: true,
      }),
      base64SetPlugin(),
    ],
  };
});