npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@jiayouzuo/vite-module-federation-core

v0.6.5

Published

Vite插件:模块联邦核心实现

Downloads

421

Readme

@jiayouzuo/vite-module-federation-core

Vite 模块联邦插件,支持微前端架构中的模块共享与远程加载。

安装

pnpm add @jiayouzuo/vite-module-federation-core

功能特性

  • 支持 exposes 暴露模块
  • 支持 remotes 消费远程模块
  • 支持 shared 共享依赖
  • 支持 exposesremotes 同时使用
  • 支持 singleton 单例模式
  • 支持 strictVersion 严格版本校验
  • 支持开发环境和生产环境
  • 支持 Vue 和 React 项目

Vue 示例

远程应用(暴露模块)

// remote-vue-app/vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import federation from '@jiayouzuo/vite-module-federation-core'

export default defineConfig({
  plugins: [
    vue(),
    federation({
      // 模块名称,主应用通过此名称引用
      name: 'remoteVueApp',
      // 远程入口文件名
      filename: 'remoteEntry.js',
      // 暴露的模块,key 为导出名,value 为文件路径
      exposes: {
        './Button': './src/components/Button.vue',
        './Card': './src/components/Card.vue',
        './utils': './src/utils/index.ts'
      },
      // 共享依赖,避免重复加载
      shared: {
        vue: {
          singleton: true,  // 单例模式,确保只有一个 Vue 实例
          requiredVersion: '^3.0.0'
        }
      }
    })
  ],
  // 需要 es2022 或更高
  build: {
    target: 'es2022',
    minify: false
  }
})

主应用(消费远程模块)

// host-vue-app/vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import federation from '@jiayouzuo/vite-module-federation-core'

export default defineConfig({
  plugins: [
    vue(),
    federation({
      name: 'hostVueApp',
      // 远程模块配置
      remotes: {
        // key: 引用名称,value: 远程入口地址
        remoteVueApp: 'http://localhost:5001/assets/remoteEntry.js'
      },
      // 共享依赖配置需与远程应用一致
      shared: {
        vue: {
          singleton: true,
          requiredVersion: '^3.0.0'
        }
      }
    })
  ],
  build: {
    target: 'es2022',
    minify: false
  }
})

使用远程 Vue 组件

<!-- host-vue-app/src/App.vue -->
<script setup lang="ts">
import { defineAsyncComponent } from 'vue'

// 方式1: 动态导入(推荐,支持懒加载)
const RemoteButton = defineAsyncComponent(() => import('remoteVueApp/Button'))
const RemoteCard = defineAsyncComponent(() => import('remoteVueApp/Card'))

// 方式2: 导入工具函数
import { formatDate } from 'remoteVueApp/utils'
</script>

<template>
  <div>
    <h1>主应用</h1>
    <!-- 使用远程组件 -->
    <RemoteButton @click="handleClick">远程按钮</RemoteButton>
    <RemoteCard title="远程卡片" />
  </div>
</template>

React 示例

远程应用(暴露模块)

// remote-react-app/vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import federation from '@jiayouzuo/vite-module-federation-core'

export default defineConfig({
  plugins: [
    react(),
    federation({
      name: 'remoteReactApp',
      filename: 'remoteEntry.js',
      // 暴露 React 组件
      exposes: {
        './Button': './src/components/Button.tsx',
        './Modal': './src/components/Modal.tsx',
        './hooks': './src/hooks/index.ts'
      },
      shared: {
        // React 必须使用单例模式,否则会报 hooks 错误
        react: {
          singleton: true,
          requiredVersion: '^18.0.0'
        },
        'react-dom': {
          singleton: true,
          requiredVersion: '^18.0.0'
        }
      }
    })
  ],
  build: {
    target: 'es2022',
    minify: false
  }
})

主应用(消费远程模块)

// host-react-app/vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import federation from '@jiayouzuo/vite-module-federation-core'

export default defineConfig({
  plugins: [
    react(),
    federation({
      name: 'hostReactApp',
      remotes: {
        remoteReactApp: 'http://localhost:5002/assets/remoteEntry.js'
      },
      shared: {
        react: {
          singleton: true,
          requiredVersion: '^18.0.0'
        },
        'react-dom': {
          singleton: true,
          requiredVersion: '^18.0.0'
        }
      }
    })
  ],
  build: {
    target: 'es2022',
    minify: false
  }
})

使用远程 React 组件

// host-react-app/src/App.tsx
import React, { lazy, Suspense } from 'react'

// 动态导入远程组件
const RemoteButton = lazy(() => import('remoteReactApp/Button'))
const RemoteModal = lazy(() => import('remoteReactApp/Modal'))

// 导入远程 hooks
import { useCounter } from 'remoteReactApp/hooks'

function App() {
  const { count, increment } = useCounter()

  return (
    <div>
      <h1>主应用</h1>
      {/* 使用 Suspense 包裹远程组件 */}
      <Suspense fallback={<div>加载中...</div>}>
        <RemoteButton onClick={increment}>
          点击次数: {count}
        </RemoteButton>
        <RemoteModal title="远程弹窗" />
      </Suspense>
    </div>
  )
}

export default App

混合使用(同时作为主应用和远程应用)

// middle-app/vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import federation from '@jiayouzuo/vite-module-federation-core'

export default defineConfig({
  plugins: [
    vue(),
    federation({
      name: 'middleApp',
      filename: 'remoteEntry.js',
      // 暴露自己的模块给其他应用
      exposes: {
        './Header': './src/components/Header.vue',
        './Footer': './src/components/Footer.vue'
      },
      // 同时消费其他远程模块
      remotes: {
        remoteVueApp: 'http://localhost:5001/assets/remoteEntry.js',
        remoteReactApp: 'http://localhost:5002/assets/remoteEntry.js'
      },
      shared: {
        vue: { singleton: true }
      }
    })
  ],
  build: {
    target: 'es2022'
  }
})

配置项

基础配置

| 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | name | string | 是 | 模块名称,其他应用通过此名称引用 | | filename | string | 否 | 远程入口文件名,默认 remoteEntry.js | | exposes | object | 否 | 暴露的模块,key 为导出路径,value 为文件路径 | | remotes | object | 否 | 远程模块,key 为引用名称,value 为入口地址 | | shared | array/object | 否 | 共享依赖配置 | | shareScope | string | 否 | 共享作用域,默认 default |

shared 配置

shared: {
  // 简单写法:直接写包名
  lodash: {},

  // 完整配置
  vue: {
    // 单例模式:强制使用同一版本
    // Vue/React 必须开启,否则会出现多实例问题
    singleton: true,

    // 严格版本:版本不匹配时抛出错误而不是回退到本地
    strictVersion: false,

    // 要求的版本范围
    requiredVersion: '^3.0.0',

    // 当前提供的版本(通常自动从 package.json 读取)
    version: '3.4.0',

    // 是否生成共享 chunk,默认 true
    generate: true,

    // 是否预加载到 HTML head
    modulePreload: false
  }
}

// 数组简写
shared: ['vue', 'pinia', 'lodash']

remotes 配置

remotes: {
  // 简单写法:直接写入口地址
  remoteApp: 'http://localhost:5001/assets/remoteEntry.js',

  // 完整配置
  remoteApp2: {
    // 远程入口地址
    external: 'http://localhost:5002/assets/remoteEntry.js',
    // 模块格式:esm | systemjs | var
    format: 'esm',
    // 来源框架:vite | webpack
    from: 'vite'
  },

  // 动态地址(运行时决定)
  dynamicApp: {
    external: `Promise.resolve(window.REMOTE_URL || 'http://localhost:5003/assets/remoteEntry.js')`,
    externalType: 'promise',
    format: 'esm',
    from: 'vite'
  }
}

exposes 配置

exposes: {
  // 简单写法
  './Button': './src/components/Button.vue',

  // 完整配置
  './Card': {
    import: './src/components/Card.vue',
    // 是否阻止样式自动注入到 head
    dontAppendStylesToHead: false
  }
}

类型声明

为远程模块添加类型声明:

// src/types/remote.d.ts

// Vue 远程模块
declare module 'remoteVueApp/Button' {
  import { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

declare module 'remoteVueApp/utils' {
  export function formatDate(date: Date): string
}

// React 远程模块
declare module 'remoteReactApp/Button' {
  import { FC } from 'react'
  interface ButtonProps {
    onClick?: () => void
    children?: React.ReactNode
  }
  const Button: FC<ButtonProps>
  export default Button
}

declare module 'remoteReactApp/hooks' {
  export function useCounter(): {
    count: number
    increment: () => void
  }
}

注意事项

  1. build.target 需要设置为 es2022 或更高(因为使用了顶层 await、??= 等语法)
  2. React 项目必须对 react 和 react-dom 开启 singleton,否则会报 hooks 相关错误
  3. Vue 项目建议对 vue 开启 singleton,避免多实例问题
  4. 共享依赖版本需要兼容,主应用和远程应用的依赖版本差异过大可能导致问题
  5. 开发环境和生产环境地址不同,可通过环境变量区分配置

License

MIT