项目技术栈:
主项目react+webpack;子项目vue3+vite;微前端框架为qiankun。然后由于qiankun不支持vite,用到了vite-plugin-qiankun这个插件。
插件的GitHub地址如下:
静态资源的请求:
错误原因:
原项目中是使用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,如图
但是由于一个项目可能要在不同的环境上部署,那这样的话部署前都需要改一下url,非常麻烦,而且写死,非常非常非常不优雅!!
3.base配置:
由于域名部分在开发环境中不会被使用,所以这个方法无法解决开发环境的问题。
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(),
],
};
});