vue-cli 5接入模块联邦 module federation

vue-cli 5接入模块联邦 module federation

模块联邦概念

模块联邦由webpack 5最先推出的,让应用加载远程的代码模块来实现不同的Web应用共享代码片段.模块联邦分为两个角色,一个是生产者,一个是消费者.生产者暴露代码供消费者消费

(用一个不太精准的比喻 这个就是webpack内置的cdn)

实现思路

  1. 首先要先将vue-cli升级到5 具体在上一篇
  2. 针对模块联邦进行配置

配置

我是vue-cli 接入webpack应用,vue-cli接vue-cli用vue-cli的配置就好了
webpack生产者 webpack.config.js

js 复制代码
const { ModuleFederationPlugin } = require("webpack").container;
const path = require("path");

module.exports = {
  entry: "./index.js",
  mode: "development",
  output: {
    publicPath: "http://localhost:6780/",
    clean: true,
  },
  devServer: {
    static: {
      directory: path.join(__dirname, "dist"),
    },
    compress: true,
    port: 6780,
  },
  optimization: {
    splitChunks: false,//splitChunks和mf冲突不能用
  },
  plugins: [
    new ModuleFederationPlugin({
      name: "moduleFederationLib",
      filename: "remoteEntry.js",
      library: { type: "window", name: "moduleFederationLib" },
      exposes: {
        "./react": "react",
        "./react-dom": "react-dom",
        './apiUrl':"./src/utils/apiUrl"
      },
    }),
  ],
};

vue-cli生产者 vue.config.js

js 复制代码
// vue.config.js
module.exports = {
  publicPath: "http://localhost:4567/",

  chainWebpack: (config) => {
    /* module federation plugin import */
    config.optimization.delete("splitChunks");
    config
      .plugin("module-federation-plugin")
      .use(require("webpack").container.ModuleFederationPlugin, [
        {
          name: "home", // 模块名称(必须唯一)
          filename: "remoteEntry.js",//加载的文件名
          library: { type: "window", name: "home" },//type:指定如何将远程模块暴露给其他应用 设置成window才能找到
          exposes: {
            // 对外暴露的组件
            "./HelloWorld": "./src/components/HelloWorld.vue",
          },
        },
      ]);
  },
  // devSever 一定要设置跨域 能够跨域是整个mf的基础
  devServer: {
    port: 4567,
    hot: true,
    headers: {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
      "Access-Control-Allow-Headers":
        "X-Requested-With, content-type, Authorization",
    },
  },
};

vue-cli消费者 webpack.config.js

js 复制代码
module.exports = {
  configureWebpack: {
    resolve: {
      fallback: {
        //禁止webpack在找不到引入的文件的时候用fs模块去查找
        //模块联邦的模块就是找不到的 webpack尝试在/src下找 在不到再报错 根本就不到远程
        fs: false 
      }
    },
  },
  chainWebpack: (config) => {
    /* module federation plugin import */
    config.optimization.delete("splitChunks");//splitChunks和mf冲突不能用
    config
      .plugin("module-federation-plugin")
      .use(require("webpack").container.ModuleFederationPlugin, [
        {
          name: "app",
          remotes: {
            // 导入 
            home: "home@http://localhost:4567/remoteEntry.js",
            "moduleFederationLib"://remote模块的module Name是不能带 - 不然会导致导入失败
            "moduleFederationLib@http://localhost:6780/remoteEntry.js",
          },
        },
      ]);
  },
};

消费者使用:

html 复制代码
<script>
export default {
  name: 'App',
  components: {
    HelloWorld: () => import('home/HelloWorld')
  },
  mounted() {
    //采用异步导入
    import('moduleFederationLib/apiUrl').then(({default: apiUrl}) =>{
      console.log('apiUrl!',apiUrl)
    })
  }
}
</script>

遇到的问题:

问题1.引入远程模块后Uncaught TypeError: Cannot read properties of undefined (reading 'call'),不引入就没有这个问题

解决方法:

  1. 检查生产者的remoteEntry.js是否正确启动
  2. 检查config中library是否已经设置成window,如果成功设置成window在控制台可以检查

问题2.ScriptExternalLoadError: Loading script failed

解决方法:

  1. 检查splitChunks是否已经设置成false
  2. 检查生产者的remoteEntry.js是否正确启动

问题3.不能够像webpack示例一样 使用静态导入远程模块

原因:

mf提供的模块是远程模块,必须要先加载远程模块才能够像静态模块一样使用

解决方法:

使用动态加载远程模块,再加载消费者
注意 :import 静态导入的模块会提升至顶层,所以必须使用动态导入
bootstrap.js

js 复制代码
//bootstrap.js
import Vue from 'vue';
Vue.config.productionTip = false;

const loadRemoteAndInitApp = async () => {
  try {
    //先动态导入远程模块
    const remote = await import('moduleFederationLib/apiUrl');
    console.log('Successfully loaded remote component:', remote);
    //导入成功之后再加载App.vue(消费模块的页面) 一定要确保先加载模块再导入消费者
    const App = (await import('./App.vue')).default;

    //创建并挂载 Vue 实例
    new Vue({
      render: h => h(App),
    }).$mount('#app');

    console.log('Vue app has been mounted.');
  } catch (error) {
    console.error('Error loading remote component or initializing Vue app:', error);
  }
};

loadRemoteAndInitApp();

main.js

js 复制代码
import './bootstrap'

远程模块消费者App.vue

js 复制代码
import APIURl from 'moduleFederationLib/apiUrl'
// 下面就跟正常从文件夹导入就行
相关推荐
福兮说5 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
郑州光合科技余经理5 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
专业程序开发源6 小时前
springboot简历管理系统81389-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·php·课程设计
专业程序开发源6 小时前
springboot社区养老系统44071-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·php·课程设计
小呆呆6666 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
凤城老人6 小时前
从 PyQt6 到 Electron:给 Edge TTS 做一个“多角色配音机“的踩坑手记
javascript·typescript·electron
Dovis(誓平步青云)6 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan7 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_7 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
IT_陈寒8 小时前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端