谈谈微前端的模块

背景

微前端将主子模块环境隔离开,那么同时也将微前端模块代码进行了隔离,这样打包就会产生重复代码,比如 react模块代码 主应用里面也有,子应用也有,所以一般也会有几种共享代码的方式

代码共享

一、Garfish

Garfish原生提供一种方式就是 setExternal 这个方法,你可以将共享的模块代码放一块

主模块

import axios from ""
Garfish.setExternal({
    axios: axios, // key 必须是模块名称,不能变化
})
复制代码

但是光主模块这么弄是不行的,子模块也得改动

  1. 子模块必须打包成 umd 格式
  1. 共享模块代码必须设置成webpack 的 externals externals: {axios: axios}

原理

其实原理很简单,setExternal 本身没有很复杂,只是把参数存起来,重点是子模块的代码

// 这块是Garfish解析子应用注入进去的代码
(function(window, module, exports, require, __GARFISH_EXPORTS__) {
    // 这部分是 webpack 打包成umd的umd模块格式
    ;!function(e, t) { 
        if ("object" == typeof exports && "object" == typeof module)
            module.exports = t(require("byted-tea-sdk"));
        else if ("function" == typeof define && define.amd)
            define(["byted-tea-sdk"], t);
        else {
            var r = "object" == typeof exports ? t(require("byted-tea-sdk")) : t(e["byted-tea-sdk"]);
            for (var n in r)
                ("object" == typeof exports ? exports : e)[n] = r[n]
        }
    }(window, (function(e) { // 这里的参数就是externals打包出来的,一般你写几个externals,就会有几个参数
        // 这里是子模块打包出来的东西
        ...
    })
  // 这块是Garfish解析子应用注入进去的代码
 }).call(
    window.__garfish__exec_temporary__.window, // Garfish提供的window 快照
    window.__garfish__exec_temporary__.window, // Garfish提供的window 快照
    window.__garfish__exec_temporary__.module, // 只要是个对象就行,
    window.__garfish__exec_temporary__.exports,// 目的只是为了让umd解析成commonjs
    window.__garfish__exec_temporary__.require,// 重写require
    window.__garfish__exec_temporary__.__GARFISH_EXPORTS__
 )
复制代码

接下来只需要简单的写一个重写require就行

window.__garfish__exec_temporary__.require = (id) => {
    return Garfish.getExternal()[id]
}
复制代码

总结

缺点: webpack的external是有局限的,一般只用第三方模块,非第三方模块不是很好用

二、模块联邦

webpack出了个模块联邦,可以把代码导出给别的项目使用,原理就不细聊了,简单贴个配置

// 主模块
plugins: [
    new ModuleFederationPlugin({
      name: "CommentMainShared",
      filename: "remoteEntry.js",
      exposes: {
          "main": path.resolve(__dirname, "src/main.js"),
          axios: "axios", ...
      }
     })
]
// 子模块模块
plugins: [
   new webpack.NormalModuleReplacementPlugin(
      /^axios$/,
      (v) => {
        v.request = `CommentMainShared/` + v.request;
      }
    ),
    new ModuleFederationPlugin({
      name: "CommentModuleMainShared",
      filename: "remoteEntry.js",
      remotes: {
        CommentMainShared: "CommentMainShared@https://localost:9999/shared/main/remoteEntry.js"
      }
    })
]
复制代码

总结

非第三方代码可以共用了,主应用可以任意导出内容,而且不需要setExternal那样严格,又是umd又是配置的,但是难道就没有缺陷了吗?

有的,那就是模块联邦真的就只是导出模块代码而已,并不会共用模块,注意这句话,一般模块加载之后都会缓存,下次就不会再次加载了,但是模块联邦只是导出代码,也就是说主应用加载过的模块,子应用会重新加载,不会复用缓存,那就要注意了,如果你的导出共享模块是有副作用的,子应用可能有点问题

猜你喜欢

转载自juejin.im/post/7096849643954241566
今日推荐