You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qwik+Vite模块联邦跨站导入组件遇ESM及require错误

基于Qwik+Vite的模块联邦组件复用问题解决方案

问题背景

  • 技术栈:两个Qwik项目(基于Vite、ESM、TypeScript),Node.js 22.3.20
  • 需求:网站B(Host)导入网站A(Remote)暴露的组件,实现跨站组件复用
  • 核心问题:
    1. 使用vite-plugin-federation时,触发ESM默认加载器不支持HTTP协议错误
    2. 改用module-federation-vite时,出现require未定义错误

问题1:vite-plugin-federation的ESM HTTP协议错误

错误原因

Node.js默认ESM加载器仅支持file:和data:协议的URL,SSR阶段直接导入HTTP地址的remoteEntry.js会触发该限制。

解决方案

通过区分客户端与SSR的远程配置,避免在Node环境中加载HTTP资源:

  1. Host端Vite配置调整
    根据ssrBuild变量切换远程地址的加载方式,SSR阶段使用本地可访问的remoteEntry.js路径(需确保Remote的dist目录可被Host访问,或通过静态资源服务代理):

    import { defineConfig } from 'vite';
    import { qwikVite } from '@builder.io/qwik/optimizer';
    import qwikCity from '@builder.io/qwik-city/vite';
    import tsconfigPaths from 'vite-tsconfig-paths';
    import federation from '@originjs/vite-plugin-federation';
    
    export default defineConfig(({ ssrBuild }) => ({
      plugins: [
        qwikCity(),
        qwikVite(),
        tsconfigPaths(),
        federation({
          name: "b",
          remotes: {
            a: {
              external: 'http://localhost:5173/dist/assets/remoteEntry.js',
              import: ssrBuild 
                ? './path/to/remote/dist/assets/remoteEntry.js' // SSR用本地路径
                : 'http://localhost:5173/dist/assets/remoteEntry.js' // 客户端用HTTP地址
            }
          }
        })
      ]
    }));
    
  2. 代码中客户端按需加载
    在Host的组件中,仅在客户端环境加载远程组件,避免SSR阶段执行HTTP导入:

    import { component$, useSignal, useClientEffect$ } from '@builder.io/qwik';
    
    export default component$(() => {
      const RemoteHeading = useSignal(null);
      
      // 仅在浏览器环境加载远程组件
      useClientEffect$(() => {
        import('a/Heading').then(mod => {
          RemoteHeading.value = mod.default;
        });
      });
      
      return <>{RemoteHeading.value && <RemoteHeading.value />}</>;
    });
    

问题2:module-federation-vite的require未定义错误

错误原因

插件生成的虚拟加载文件使用了CommonJS的require语法,但Qwik项目为纯ESM环境,Node.js在ESM模式下不支持require。

解决方案

  1. 强制生成ESM兼容代码
    在Host的Vite配置中明确指定输出格式为ESM,并配置插件启用模块模式:

    import { defineConfig } from 'vite';
    import { qwikVite } from '@builder.io/qwik/optimizer';
    import qwikCity from '@builder.io/qwik-city/vite';
    import tsconfigPaths from 'vite-tsconfig-paths';
    import federation from 'module-federation-vite';
    
    export default defineConfig({
      plugins: [
        qwikCity(),
        qwikVite(),
        tsconfigPaths(),
        federation({
          name: "b",
          remotes: {
            a: {
              type: 'module',
              name: 'a',
              entry: 'http://localhost:5173/dist/assets/remoteEntry.js',
              shareScope: "default"
            }
          },
          output: { format: 'es' }
        })
      ],
      build: {
        rollupOptions: {
          output: { format: 'esm' }
        }
      }
    });
    
  2. 手动修复虚拟文件的require语法
    通过Vite的transform钩子,将插件生成的虚拟文件中的require替换为import:

    export default defineConfig({
      plugins: [
        // ...其他插件
        {
          name: 'fix-mf-require',
          transform(code, id) {
            if (id.includes('__mf__virtual')) {
              return code.replace(/require\(/g, 'import(');
            }
            return code;
          }
        }
      ]
    });
    

内容的提问来源于stack exchange,提问作者Justin Slijkhuis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 19:55:54