Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: manage shareStrategy option #105

Merged
merged 1 commit into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 68 additions & 80 deletions src/utils/normalizeModuleFederationOptions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SharedConfig } from '@module-federation/runtime/types';
import { SharedConfig, ShareStrategy } from '@module-federation/runtime/types';

export type RemoteEntryType =
| 'var'
Expand Down Expand Up @@ -29,7 +29,13 @@ interface ExposesItem {
export interface NormalizedShared {
[key: string]: ShareItem;
}
export interface RemoteObjectConfig { type?: string; name: string; entry: string; entryGlobalName?: string; shareScope?: string }
export interface RemoteObjectConfig {
type?: string;
name: string;
entry: string;
entryGlobalName?: string;
shareScope?: string;
}

function normalizeExposesItem(key: string, item: string | { import: string }): ExposesItem {
let importPath: string = '';
Expand All @@ -56,22 +62,10 @@ function normalizeExposes(
}

export function normalizeRemotes(
remotes:
| Record<
string,
| string
| RemoteObjectConfig
>
| undefined
): Record<
string,
RemoteObjectConfig
> {
remotes: Record<string, string | RemoteObjectConfig> | undefined
): Record<string, RemoteObjectConfig> {
if (!remotes) return {};
const result: Record<
string,
RemoteObjectConfig
> = {};
const result: Record<string, RemoteObjectConfig> = {};
if (typeof remotes === 'object') {
Object.keys(remotes).forEach((key) => {
result[key] = normalizeRemoteItem(key, remotes[key]);
Expand All @@ -80,12 +74,7 @@ export function normalizeRemotes(
return result;
}

function normalizeRemoteItem(
key: string,
remote:
| string
| RemoteObjectConfig
): RemoteObjectConfig {
function normalizeRemoteItem(key: string, remote: string | RemoteObjectConfig): RemoteObjectConfig {
if (typeof remote === 'string') {
const [entryGlobalName] = remote.split('@');
const entry = remote.replace(entryGlobalName + '@', '');
Expand Down Expand Up @@ -132,13 +121,13 @@ function normalizeShareItem(
shareItem:
| string
| {
name: string;
version?: string;
shareScope?: string;
singleton?: boolean;
requiredVersion?: string;
strictVersion?: boolean;
}
name: string;
version?: string;
shareScope?: string;
singleton?: boolean;
requiredVersion?: string;
strictVersion?: boolean;
}
): ShareItem {
let version: string | undefined;
try {
Expand Down Expand Up @@ -175,17 +164,17 @@ function normalizeShared(
shared:
| string[]
| Record<
string,
| string
| {
name?: string;
version?: string;
shareScope?: string;
singleton?: boolean;
requiredVersion?: string;
strictVersion?: boolean;
}
>
string,
| string
| {
name?: string;
version?: string;
shareScope?: string;
singleton?: boolean;
requiredVersion?: string;
strictVersion?: boolean;
}
>
| undefined
): NormalizedShared {
if (!shared) return {};
Expand Down Expand Up @@ -216,14 +205,17 @@ interface ManifestOptions {
fileName?: string;
}
function normalizeManifest(manifest: ModuleFederationOptions['manifest'] = false) {
if (typeof manifest === "boolean") {
return manifest
if (typeof manifest === 'boolean') {
return manifest;
}
return Object.assign({
filePath: "",
disableAssetsAnalyze: false,
fileName: "mf-manifest.json"
}, manifest)
return Object.assign(
{
filePath: '',
disableAssetsAnalyze: false,
fileName: 'mf-manifest.json',
},
manifest
);
}

export type ModuleFederationOptions = {
Expand All @@ -232,36 +224,31 @@ export type ModuleFederationOptions = {
library?: any;
name: string;
// remoteType?: string;
remotes?:
| Record<
string,
| string
| RemoteObjectConfig
>
| undefined;
remotes?: Record<string, string | RemoteObjectConfig> | undefined;
runtime?: any;
shareScope?: string;
shared?:
| string[]
| Record<
string,
| string
| {
name?: string;
version?: string;
shareScope?: string;
singleton?: boolean;
requiredVersion?: string;
strictVersion?: boolean;
}
>
| undefined;
| string[]
| Record<
string,
| string
| {
name?: string;
version?: string;
shareScope?: string;
singleton?: boolean;
requiredVersion?: string;
strictVersion?: boolean;
}
>
| undefined;
runtimePlugins?: string[];
getPublicPath?: any;
implementation?: any;
manifest?: ManifestOptions | boolean;
dev?: any;
dts?: any;
shareStrategy: ShareStrategy;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be optional?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, nice catch. Would you like to drop a PR for that? you deserve it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Certainly! #130

};

export interface NormalizedModuleFederationOptions {
Expand All @@ -270,10 +257,7 @@ export interface NormalizedModuleFederationOptions {
library: any;
name: string;
// remoteType: string;
remotes: Record<
string,
RemoteObjectConfig
>;
remotes: Record<string, RemoteObjectConfig>;
runtime: any;
shareScope: string;
shared: NormalizedShared;
Expand All @@ -283,23 +267,26 @@ export interface NormalizedModuleFederationOptions {
manifest: ManifestOptions | boolean;
dev: any;
dts: any;
shareStrategy?: ShareStrategy;
}

let config: NormalizedModuleFederationOptions
let config: NormalizedModuleFederationOptions;
export function getNormalizeModuleFederationOptions() {
return config
return config;
}

export function getNormalizeShareItem(key: string) {
const options = getNormalizeModuleFederationOptions()
const shareItem = options.shared[removePathFromNpmPackage(key)] || options.shared[removePathFromNpmPackage(key) + "/"]
return shareItem
const options = getNormalizeModuleFederationOptions();
const shareItem =
options.shared[removePathFromNpmPackage(key)] ||
options.shared[removePathFromNpmPackage(key) + '/'];
return shareItem;
}

export function normalizeModuleFederationOptions(
options: ModuleFederationOptions
): NormalizedModuleFederationOptions {
return config = {
return (config = {
exposes: normalizeExposes(options.exposes),
filename: options.filename || 'remoteEntry-[hash]',
library: normalizeLibrary(options.library),
Expand All @@ -315,5 +302,6 @@ export function normalizeModuleFederationOptions(
manifest: normalizeManifest(options.manifest),
dev: options.dev,
dts: options.dts,
};
shareStrategy: options.shareStrategy,
});
}
71 changes: 41 additions & 30 deletions src/virtualModules/virtualRemoteEntry.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,59 @@
import { getLocalSharedImportMapPath_temp, writeLocalSharedImportMap_temp } from '../utils/localSharedImportMap_temp';
import { getNormalizeModuleFederationOptions, getNormalizeShareItem, NormalizedModuleFederationOptions } from '../utils/normalizeModuleFederationOptions';
import {
getLocalSharedImportMapPath_temp,
writeLocalSharedImportMap_temp,
} from '../utils/localSharedImportMap_temp';
import {
getNormalizeModuleFederationOptions,
getNormalizeShareItem,
NormalizedModuleFederationOptions,
} from '../utils/normalizeModuleFederationOptions';
import VirtualModule from '../utils/VirtualModule';
import { getUsedRemotesMap } from './virtualRemotes';
import { virtualRuntimeInitStatus } from './virtualRuntimeInitStatus';
import { getPreBuildLibImportId } from './virtualShared_preBuild';

let usedShares: Set<string> = new Set()
let usedShares: Set<string> = new Set();
export function getUsedShares() {
return usedShares
return usedShares;
}
export function addUsedShares(pkg: string) {
usedShares.add(pkg)
usedShares.add(pkg);
}
// *** Expose locally provided shared modules here
const localSharedImportMapModule = new VirtualModule("localSharedImportMap")
const localSharedImportMapModule = new VirtualModule('localSharedImportMap');
export function getLocalSharedImportMapPath() {
return getLocalSharedImportMapPath_temp()
return getLocalSharedImportMapPath_temp();
// return localSharedImportMapModule.getPath()
}
let prevSharedCount: number | undefined
let prevSharedCount: number | undefined;
export function writeLocalSharedImportMap() {
const sharedCount = getUsedShares().size
const sharedCount = getUsedShares().size;
if (prevSharedCount !== sharedCount) {
prevSharedCount = sharedCount
writeLocalSharedImportMap_temp(generateLocalSharedImportMap())
prevSharedCount = sharedCount;
writeLocalSharedImportMap_temp(generateLocalSharedImportMap());
// localSharedImportMapModule.writeSync(generateLocalSharedImportMap(), true)
}
}
export function generateLocalSharedImportMap() {
const options = getNormalizeModuleFederationOptions()
const options = getNormalizeModuleFederationOptions();
return `
const importMap = {
${Array.from(getUsedShares()).map(pkg => `
${Array.from(getUsedShares())
.map(
(pkg) => `
${JSON.stringify(pkg)}: async () => {
let pkg = await import("${getPreBuildLibImportId(pkg)}")
return pkg
}
`).join(",")}
`
)
.join(',')}
}
const usedShared = {
${Array.from(getUsedShares())
.map((key) => {
const shareItem = getNormalizeShareItem(key);
return `
.map((key) => {
const shareItem = getNormalizeShareItem(key);
return `
${JSON.stringify(key)}: {
name: ${JSON.stringify(key)},
version: ${JSON.stringify(shareItem.version)},
Expand All @@ -69,28 +80,28 @@ export function generateLocalSharedImportMap() {
}
}
`;
})
.join(',')}
})
.join(',')}
}
const usedRemotes = [${Object.keys(getUsedRemotesMap())
.map((key) => {
const remote = options.remotes[key];
return `
.map((key) => {
const remote = options.remotes[key];
return `
{
entryGlobalName: ${JSON.stringify(remote.entryGlobalName)},
name: ${JSON.stringify(remote.name)},
type: ${JSON.stringify(remote.type)},
entry: ${JSON.stringify(remote.entry)},
}
`;
})
.join(',')}
})
.join(',')}
]
export {
usedShared,
usedRemotes
}
`
`;
}

export const REMOTE_ENTRY_ID = 'virtual:mf-REMOTE_ENTRY_ID';
Expand Down Expand Up @@ -131,8 +142,8 @@ export function generateRemoteEntry(options: NormalizedModuleFederationOptions):
name: ${JSON.stringify(options.name)},
remotes: usedRemotes,
shared: usedShared,
plugins: [${pluginImportNames.map((item) => `${item[0]}()`).join(', ')}]
});
plugins: [${pluginImportNames.map((item) => `${item[0]}()`).join(', ')}],
${options.shareStrategy ? `shareStrategy: ${options.shareStrategy}` : ''});
initRes.initShareScopeMap('${options.shareScope}', shared);
initResolve(initRes)
return initRes
Expand All @@ -153,16 +164,16 @@ export function generateRemoteEntry(options: NormalizedModuleFederationOptions):
* Inject entry file, automatically init when used as host,
* and will not inject remoteEntry
*/
const hostAutoInitModule = new VirtualModule("hostAutoInit")
const hostAutoInitModule = new VirtualModule('hostAutoInit');
export function writeHostAutoInit() {
hostAutoInitModule.writeSync(`
import {init} from "${REMOTE_ENTRY_ID}"
init()
`)
`);
}
export function getHostAutoInitImportId() {
return hostAutoInitModule.getImportId();
}
export function getHostAutoInitPath() {
return hostAutoInitModule.getPath();
}
}