背景
微前端将主子模块环境隔离开,那么同时也将微前端模块代码进行了隔离,这样打包就会产生重复代码,比如 react模块代码 主应用里面也有,子应用也有,所以一般也会有几种共享代码的方式
代码共享
一、Garfish
Garfish原生提供一种方式就是 setExternal
这个方法,你可以将共享的模块代码放一块
主模块
import axios from ""
Garfish.setExternal({
axios: axios, // key 必须是模块名称,不能变化
})
复制代码
但是光主模块这么弄是不行的,子模块也得改动
- 子模块必须打包成 umd 格式
- 共享模块代码必须设置成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又是配置的,但是难道就没有缺陷了吗?
有的,那就是模块联邦真的就只是导出模块代码而已,并不会共用模块,注意这句话,一般模块加载之后都会缓存,下次就不会再次加载了,但是模块联邦只是导出代码,也就是说主应用加载过的模块,子应用会重新加载,不会复用缓存,那就要注意了,如果你的导出共享模块是有副作用的,子应用可能有点问题