-
Notifications
You must be signed in to change notification settings - Fork 295
shared [deprecated]
Shared 主要是为了 防止host 端和 remote 端多次加载相同依赖而设置的。
打包阶段依赖于 rollup 的打包功能,当你在 rollup.config.js/vite.config.js 中配置如下代码时
plugins:[
federation ({
shared:['vue','vuex']
})
]federation 插件会在 rollup options 钩子时读取 shared 相关配置
然后将其作为入口文件打包,也就是将会把 vue、vuex 作为入口文件,类似于下面的配置,__federation_shared_ 开头的是根据 shared 配置加入的入口文件
现在会使用this.emitFile()来添加入口文件,因为shared特性依赖于preserveSignature属性的配置,该方法可以更改单个chunk的配置而不会影响用户的配置
type EmittedChunk = {
type: 'chunk';
id: string;
name?: string;
fileName?: string;
implicitlyLoadedAfterOneOf?: string[];
importer?: string;
preserveSignature?: 'strict' | 'allow-extension' | 'exports-only' | false;
};如果没有配置 manualChunks,vite 默认会提供一个如下的 manualChunks 实现
function createMoveToVendorChunkFn (config: ResolvedConfig): GetManualChunk {
const cache = new Map<string, boolean>()
return (id, { getModuleInfo }) => {
if (
id.includes ('node_modules') &&
!isCSSRequest (id) &&
staticImportedByEntry (id, getModuleInfo, cache)
) {
return 'vendor'
}
}
}简单理解就是如果 moduleId 包含了 node_modules,就会将这部分全部打包到 vendor 中,也就是将所有 shared 相关的配置全部打包到一个文件中。
我们需要的是每一个 shared 配置都单独打一个包,所以如果检测到用户配置了 manualChunks 函数实现(不论是用户配置的还是 vite 配置的),都将会代理这个函数,简要实现如下
if (typeof outputOption.manualChunks === 'function') {
outputOption.manualChunks = new Proxy (outputOption.manualChunks, {
apply (target, thisArg, argArray) {
const moduleId = argArray [0]
// if id is in shareModuleIds , return id ,else return vite function value
let find = ''
for (const sharedMapElement of sharedMap) {
//shared key,such as vue,vuex...
const key = sharedMapElement [0]
//shared values,such as version and so on
const value = sharedMapElement [1]
if (value.get ('dependencies')?.has (id)) {
find = key
break
}
}
return find ? find : target (argArray [0], argArray [1])
}
})
}也就是如果 moduleId 如果属于 shared 依赖,将会把这部分依赖放到对应的 shared module 中,不属于就继续走用户配置的配置函数,这样就能将 shared 从 vite 的 vendor 文件中抽离出来打成单独的 chunk
例如暴露出的组件A中使用了vue
import {h} from 'vue';由于shared特性,它会被federation更改为
const vue = __federation_import('vue');
const {h} = vue__federation_import_是shared倒入的关键方法,他的大致逻辑为
function __federation_fn_import(depName){
// 省略版本判断等
return window.depName ? window.depName.get() : import('./vue.js');
}大概流程就是组件使用shared库时,会优先在window上查询,优先使用window上的shared,如果没有才会使用自身的shared。
但是window上的shared来自于哪里呢
在注册远程组件时,host端会将自身能提供的shared信息提供给remote的init方法(可以在remoteEntry.js文件中找到),remote将会把这些信息写入全局