@module-federation/metro 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modules/asyncRequire.ts +28 -3
- package/dist/modules/asyncStartup.tsx +0 -1
- package/dist/modules/metroCorePlugin.ts +0 -1
- package/dist/plugin/generators.js +6 -6
- package/dist/plugin/generators.mjs +6 -6
- package/dist/plugin/index.js +18 -3
- package/dist/plugin/index.mjs +18 -3
- package/dist/plugin/manifest-middleware.d.ts +12 -0
- package/dist/plugin/manifest-middleware.js +213 -0
- package/dist/plugin/manifest-middleware.mjs +171 -0
- package/dist/plugin/manifest.d.ts +15 -2
- package/dist/plugin/manifest.js +108 -17
- package/dist/plugin/manifest.mjs +99 -18
- package/dist/plugin/resolver.d.ts +1 -1
- package/dist/plugin/resolver.js +2 -2
- package/dist/plugin/resolver.mjs +2 -2
- package/dist/plugin/serializer.d.ts +2 -1
- package/dist/plugin/serializer.js +22 -14
- package/dist/plugin/serializer.mjs +22 -14
- package/package.json +4 -4
|
@@ -70,19 +70,44 @@ function buildLoadBundleAsyncWrapper() {
|
|
|
70
70
|
const loadBundleAsync =
|
|
71
71
|
__loadBundleAsync as typeof globalThis.__loadBundleAsync;
|
|
72
72
|
|
|
73
|
-
return async (originalBundlePath: string) => {
|
|
73
|
+
return async (originalBundlePath: string): Promise<void> => {
|
|
74
74
|
const scope = globalThis.__FEDERATION__.__NATIVE__[__METRO_GLOBAL_PREFIX__];
|
|
75
75
|
|
|
76
76
|
// entry is always in the root directory of assets associated with remote
|
|
77
77
|
// based on that, we extract the public path from the origin URL
|
|
78
78
|
// e.g. http://example.com/a/b/c/mf-manfiest.json -> http://example.com/a/b/c
|
|
79
79
|
const publicPath = getPublicPath(scope.origin);
|
|
80
|
-
|
|
80
|
+
let bundlePath = getBundlePath(originalBundlePath, publicPath);
|
|
81
|
+
|
|
82
|
+
const isSplitBundle = !isUrl(originalBundlePath);
|
|
83
|
+
|
|
84
|
+
// Cache handler registered externally (e.g. by zephyr-native-cache register()).
|
|
85
|
+
// Stored under __FEDERATION__.__NATIVE__.__CACHE__ as a singleton (no prefix scope).
|
|
86
|
+
const cacheHandler = (globalThis as any).__FEDERATION__?.__NATIVE__
|
|
87
|
+
?.__CACHE__ as
|
|
88
|
+
| ((
|
|
89
|
+
fallback: (path: string) => Promise<void>,
|
|
90
|
+
bundlePath: string,
|
|
91
|
+
) => Promise<void>)
|
|
92
|
+
| undefined;
|
|
93
|
+
|
|
94
|
+
// For remote split bundles with cache enabled, convert relative paths to
|
|
95
|
+
// full URLs so they enter the same cache path as container bundles.
|
|
96
|
+
// In dev mode, getBundlePath returns relative paths unchanged, but we need
|
|
97
|
+
// full URLs for the cache layer (download + eval).
|
|
98
|
+
if (isSplitBundle && cacheHandler && publicPath && !isUrl(bundlePath)) {
|
|
99
|
+
bundlePath = joinComponents(publicPath, bundlePath);
|
|
100
|
+
}
|
|
81
101
|
|
|
82
102
|
// ../../node_modules/ -> ..%2F..%2Fnode_modules/ so that it's not automatically sanitized
|
|
83
103
|
const encodedBundlePath = bundlePath.replaceAll('../', '..%2F');
|
|
84
104
|
|
|
85
|
-
|
|
105
|
+
let result;
|
|
106
|
+
if (cacheHandler) {
|
|
107
|
+
await cacheHandler(loadBundleAsync, encodedBundlePath);
|
|
108
|
+
} else {
|
|
109
|
+
result = await loadBundleAsync(encodedBundlePath);
|
|
110
|
+
}
|
|
86
111
|
|
|
87
112
|
// when the origin is not the same, it means we are loading a remote container
|
|
88
113
|
// we can return early since dependencies are processed differently for entry bundles
|
|
@@ -2,7 +2,6 @@ import type { Federation } from '@module-federation/runtime';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
4
|
declare global {
|
|
5
|
-
// @ts-expect-error -- Intentional redeclaration for Metro/React Native runtime global.
|
|
6
5
|
// eslint-disable-next-line no-var
|
|
7
6
|
var __DEV__: boolean;
|
|
8
7
|
// eslint-disable-next-line no-var
|
|
@@ -97,12 +97,12 @@ function generateRemotes(remotes = {}) {
|
|
|
97
97
|
const remoteEntryParts = remoteEntry.split('@');
|
|
98
98
|
const remoteName = remoteEntryParts[0];
|
|
99
99
|
const remoteEntryUrl = remoteEntryParts.slice(1).join('@');
|
|
100
|
-
remotesEntries.push(`{
|
|
101
|
-
alias:
|
|
102
|
-
name:
|
|
103
|
-
entry:
|
|
104
|
-
entryGlobalName:
|
|
105
|
-
type: "var"
|
|
100
|
+
remotesEntries.push(`{
|
|
101
|
+
alias: ${JSON.stringify(remoteAlias)},
|
|
102
|
+
name: ${JSON.stringify(remoteName)},
|
|
103
|
+
entry: ${JSON.stringify(remoteEntryUrl)},
|
|
104
|
+
entryGlobalName: ${JSON.stringify(remoteName)},
|
|
105
|
+
type: "var"
|
|
106
106
|
}`);
|
|
107
107
|
}
|
|
108
108
|
return `[${remotesEntries.join(',\n')}]`;
|
|
@@ -55,12 +55,12 @@ function generateRemotes(remotes = {}) {
|
|
|
55
55
|
const remoteEntryParts = remoteEntry.split('@');
|
|
56
56
|
const remoteName = remoteEntryParts[0];
|
|
57
57
|
const remoteEntryUrl = remoteEntryParts.slice(1).join('@');
|
|
58
|
-
remotesEntries.push(`{
|
|
59
|
-
alias:
|
|
60
|
-
name:
|
|
61
|
-
entry:
|
|
62
|
-
entryGlobalName:
|
|
63
|
-
type: "var"
|
|
58
|
+
remotesEntries.push(`{
|
|
59
|
+
alias: ${JSON.stringify(remoteAlias)},
|
|
60
|
+
name: ${JSON.stringify(remoteName)},
|
|
61
|
+
entry: ${JSON.stringify(remoteEntryUrl)},
|
|
62
|
+
entryGlobalName: ${JSON.stringify(remoteName)},
|
|
63
|
+
type: "var"
|
|
64
64
|
}`);
|
|
65
65
|
}
|
|
66
66
|
return `[${remotesEntries.join(',\n')}]`;
|
package/dist/plugin/index.js
CHANGED
|
@@ -45,6 +45,7 @@ const federated_remote_types_js_namespaceObject = require("../utils/federated-re
|
|
|
45
45
|
const external_babel_transformer_js_namespaceObject = require("./babel-transformer.js");
|
|
46
46
|
const external_helpers_js_namespaceObject = require("./helpers.js");
|
|
47
47
|
const external_manifest_js_namespaceObject = require("./manifest.js");
|
|
48
|
+
const external_manifest_middleware_js_namespaceObject = require("./manifest-middleware.js");
|
|
48
49
|
const external_normalize_extra_options_js_namespaceObject = require("./normalize-extra-options.js");
|
|
49
50
|
const external_normalize_options_js_namespaceObject = require("./normalize-options.js");
|
|
50
51
|
const external_resolver_js_namespaceObject = require("./resolver.js");
|
|
@@ -87,7 +88,12 @@ function augmentConfig(config, federationOptions, extraOptions) {
|
|
|
87
88
|
enableInitializeCorePatching: flags.unstable_patchInitializeCore,
|
|
88
89
|
enableRuntimeRequirePatching: flags.unstable_patchRuntimeRequire
|
|
89
90
|
});
|
|
90
|
-
const
|
|
91
|
+
const manifestOptions = {
|
|
92
|
+
projectRoot: config.projectRoot,
|
|
93
|
+
target: (0, external_helpers_js_namespaceObject.isUsingMFBundleCommand)() ? 'build' : 'development',
|
|
94
|
+
tmpDirPath
|
|
95
|
+
};
|
|
96
|
+
const manifestPath = (0, external_manifest_js_namespaceObject.createManifest)(options, tmpDirPath, manifestOptions);
|
|
91
97
|
(0, external_helpers_js_namespaceObject.stubHostEntry)(hostEntryPath);
|
|
92
98
|
(0, external_helpers_js_namespaceObject.stubRemoteEntry)(remoteEntryPath);
|
|
93
99
|
global.__METRO_FEDERATION_CONFIG = options;
|
|
@@ -106,7 +112,7 @@ function augmentConfig(config, federationOptions, extraOptions) {
|
|
|
106
112
|
...config,
|
|
107
113
|
serializer: {
|
|
108
114
|
...config.serializer,
|
|
109
|
-
customSerializer: (0, external_serializer_js_namespaceObject.getModuleFederationSerializer)(options, (0, external_helpers_js_namespaceObject.isUsingMFBundleCommand)()),
|
|
115
|
+
customSerializer: (0, external_serializer_js_namespaceObject.getModuleFederationSerializer)(options, (0, external_helpers_js_namespaceObject.isUsingMFBundleCommand)(), manifestPath, manifestOptions),
|
|
110
116
|
getModulesRunBeforeMainModule: (entryFilePath)=>{
|
|
111
117
|
if (flags.unstable_patchInitializeCore) return config.serializer.getModulesRunBeforeMainModule(entryFilePath);
|
|
112
118
|
if (isRemote) return [];
|
|
@@ -150,7 +156,16 @@ function augmentConfig(config, federationOptions, extraOptions) {
|
|
|
150
156
|
},
|
|
151
157
|
server: {
|
|
152
158
|
...config.server,
|
|
153
|
-
enhanceMiddleware:
|
|
159
|
+
enhanceMiddleware: (middleware, metroServer)=>{
|
|
160
|
+
const manifestMiddleware = (0, external_manifest_middleware_js_namespaceObject.createManifestMiddleware)({
|
|
161
|
+
federationConfig: options,
|
|
162
|
+
projectRoot: config.projectRoot,
|
|
163
|
+
remoteEntryPath,
|
|
164
|
+
tmpDirPath,
|
|
165
|
+
vmManager
|
|
166
|
+
})(middleware, metroServer);
|
|
167
|
+
return vmManager.getMiddleware()(manifestMiddleware, metroServer);
|
|
168
|
+
},
|
|
154
169
|
rewriteRequestUrl: (0, external_rewrite_request_js_namespaceObject.createRewriteRequest)({
|
|
155
170
|
config,
|
|
156
171
|
originalEntryFilename,
|
package/dist/plugin/index.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import { applyTypesMetaToManifest, maybeGenerateFederatedRemoteTypes } from "../
|
|
|
8
8
|
import { createBabelTransformer } from "./babel-transformer.mjs";
|
|
9
9
|
import { isUsingMFBundleCommand, isUsingMFCommand, prepareTmpDir, replaceExtension, stubHostEntry, stubRemoteEntry } from "./helpers.mjs";
|
|
10
10
|
import { createManifest } from "./manifest.mjs";
|
|
11
|
+
import { createManifestMiddleware } from "./manifest-middleware.mjs";
|
|
11
12
|
import { normalizeExtraOptions } from "./normalize-extra-options.mjs";
|
|
12
13
|
import { normalizeOptions } from "./normalize-options.mjs";
|
|
13
14
|
import { createResolveRequest } from "./resolver.mjs";
|
|
@@ -50,7 +51,12 @@ function augmentConfig(config, federationOptions, extraOptions) {
|
|
|
50
51
|
enableInitializeCorePatching: flags.unstable_patchInitializeCore,
|
|
51
52
|
enableRuntimeRequirePatching: flags.unstable_patchRuntimeRequire
|
|
52
53
|
});
|
|
53
|
-
const
|
|
54
|
+
const manifestOptions = {
|
|
55
|
+
projectRoot: config.projectRoot,
|
|
56
|
+
target: isUsingMFBundleCommand() ? 'build' : 'development',
|
|
57
|
+
tmpDirPath
|
|
58
|
+
};
|
|
59
|
+
const manifestPath = createManifest(options, tmpDirPath, manifestOptions);
|
|
54
60
|
stubHostEntry(hostEntryPath);
|
|
55
61
|
stubRemoteEntry(remoteEntryPath);
|
|
56
62
|
global.__METRO_FEDERATION_CONFIG = options;
|
|
@@ -69,7 +75,7 @@ function augmentConfig(config, federationOptions, extraOptions) {
|
|
|
69
75
|
...config,
|
|
70
76
|
serializer: {
|
|
71
77
|
...config.serializer,
|
|
72
|
-
customSerializer: getModuleFederationSerializer(options, isUsingMFBundleCommand()),
|
|
78
|
+
customSerializer: getModuleFederationSerializer(options, isUsingMFBundleCommand(), manifestPath, manifestOptions),
|
|
73
79
|
getModulesRunBeforeMainModule: (entryFilePath)=>{
|
|
74
80
|
if (flags.unstable_patchInitializeCore) return config.serializer.getModulesRunBeforeMainModule(entryFilePath);
|
|
75
81
|
if (isRemote) return [];
|
|
@@ -113,7 +119,16 @@ function augmentConfig(config, federationOptions, extraOptions) {
|
|
|
113
119
|
},
|
|
114
120
|
server: {
|
|
115
121
|
...config.server,
|
|
116
|
-
enhanceMiddleware:
|
|
122
|
+
enhanceMiddleware: (middleware, metroServer)=>{
|
|
123
|
+
const manifestMiddleware = createManifestMiddleware({
|
|
124
|
+
federationConfig: options,
|
|
125
|
+
projectRoot: config.projectRoot,
|
|
126
|
+
remoteEntryPath,
|
|
127
|
+
tmpDirPath,
|
|
128
|
+
vmManager
|
|
129
|
+
})(middleware, metroServer);
|
|
130
|
+
return vmManager.getMiddleware()(manifestMiddleware, metroServer);
|
|
131
|
+
},
|
|
117
132
|
rewriteRequestUrl: createRewriteRequest({
|
|
118
133
|
config,
|
|
119
134
|
originalEntryFilename,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ServerConfigT } from 'metro-config';
|
|
2
|
+
import type { ModuleFederationConfigNormalized } from '../types';
|
|
3
|
+
import type { VirtualModuleManager } from '../utils';
|
|
4
|
+
type ManifestMiddlewareOptions = {
|
|
5
|
+
federationConfig: ModuleFederationConfigNormalized;
|
|
6
|
+
projectRoot: string;
|
|
7
|
+
remoteEntryPath: string;
|
|
8
|
+
tmpDirPath: string;
|
|
9
|
+
vmManager: Pick<VirtualModuleManager, 'registerVirtualModule'>;
|
|
10
|
+
};
|
|
11
|
+
export declare function createManifestMiddleware({ federationConfig, projectRoot, remoteEntryPath, tmpDirPath, vmManager, }: ManifestMiddlewareOptions): NonNullable<ServerConfigT['enhanceMiddleware']>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.n = (module)=>{
|
|
5
|
+
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
6
|
+
__webpack_require__.d(getter, {
|
|
7
|
+
a: getter
|
|
8
|
+
});
|
|
9
|
+
return getter;
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
(()=>{
|
|
13
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
14
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: definition[key]
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
})();
|
|
20
|
+
(()=>{
|
|
21
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
22
|
+
})();
|
|
23
|
+
(()=>{
|
|
24
|
+
__webpack_require__.r = (exports1)=>{
|
|
25
|
+
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
26
|
+
value: 'Module'
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
29
|
+
value: true
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
})();
|
|
33
|
+
var __webpack_exports__ = {};
|
|
34
|
+
__webpack_require__.r(__webpack_exports__);
|
|
35
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
36
|
+
createManifestMiddleware: ()=>createManifestMiddleware
|
|
37
|
+
});
|
|
38
|
+
const external_node_fs_namespaceObject = require("node:fs");
|
|
39
|
+
const external_node_path_namespaceObject = require("node:path");
|
|
40
|
+
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
41
|
+
const metro_compat_js_namespaceObject = require("../utils/metro-compat.js");
|
|
42
|
+
const external_constants_js_namespaceObject = require("./constants.js");
|
|
43
|
+
const external_generators_js_namespaceObject = require("./generators.js");
|
|
44
|
+
const external_helpers_js_namespaceObject = require("./helpers.js");
|
|
45
|
+
const external_manifest_js_namespaceObject = require("./manifest.js");
|
|
46
|
+
function createManifestMiddleware({ federationConfig, projectRoot, remoteEntryPath, tmpDirPath, vmManager }) {
|
|
47
|
+
const warmups = new Map();
|
|
48
|
+
return (middleware, metroServer)=>{
|
|
49
|
+
const nextMiddleware = middleware;
|
|
50
|
+
return async (req, res, next)=>{
|
|
51
|
+
try {
|
|
52
|
+
const warmupOptions = getManifestWarmupOptions(req.url);
|
|
53
|
+
if (warmupOptions) {
|
|
54
|
+
const warmupKey = JSON.stringify(warmupOptions);
|
|
55
|
+
let warmup = warmups.get(warmupKey);
|
|
56
|
+
if (!warmup) {
|
|
57
|
+
warmup = warmManifestBundles(metroServer, {
|
|
58
|
+
federationConfig,
|
|
59
|
+
host: req.headers.host,
|
|
60
|
+
projectRoot,
|
|
61
|
+
remoteEntryPath,
|
|
62
|
+
tmpDirPath,
|
|
63
|
+
vmManager,
|
|
64
|
+
warmupOptions
|
|
65
|
+
}).finally(()=>{
|
|
66
|
+
warmups.delete(warmupKey);
|
|
67
|
+
});
|
|
68
|
+
warmups.set(warmupKey, warmup);
|
|
69
|
+
}
|
|
70
|
+
await warmup;
|
|
71
|
+
}
|
|
72
|
+
return nextMiddleware(req, res, next);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
next(error instanceof Error ? error : new Error(String(error)));
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function getManifestWarmupOptions(rawUrl) {
|
|
80
|
+
const parsedUrl = new URL(rawUrl ?? '/', 'http://localhost');
|
|
81
|
+
if (parsedUrl.pathname !== `/${external_constants_js_namespaceObject.MANIFEST_FILENAME}`) return null;
|
|
82
|
+
const platform = parsedUrl.searchParams.get('platform');
|
|
83
|
+
if (!platform) return null;
|
|
84
|
+
return {
|
|
85
|
+
dev: getBoolean(parsedUrl.searchParams, 'dev', true),
|
|
86
|
+
excludeSource: getBoolean(parsedUrl.searchParams, 'excludeSource', false),
|
|
87
|
+
minify: getBoolean(parsedUrl.searchParams, 'minify', false),
|
|
88
|
+
platform,
|
|
89
|
+
sourcePaths: parsedUrl.searchParams.get('sourcePaths') ?? void 0
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
async function warmManifestBundles(metroServer, { federationConfig, host, projectRoot, remoteEntryPath, tmpDirPath, vmManager, warmupOptions }) {
|
|
93
|
+
for (const request of getBundleWarmupRequests({
|
|
94
|
+
federationConfig,
|
|
95
|
+
projectRoot,
|
|
96
|
+
remoteEntryPath,
|
|
97
|
+
tmpDirPath,
|
|
98
|
+
vmManager
|
|
99
|
+
})){
|
|
100
|
+
if (request.virtualModule) await ensureVirtualModuleReady(request.virtualModule, vmManager);
|
|
101
|
+
await metroServer.build(getBundleOptions(request, host, warmupOptions));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function getBundleWarmupRequests({ federationConfig, projectRoot, remoteEntryPath, tmpDirPath }) {
|
|
105
|
+
const relativeTmpDirPath = (0, external_helpers_js_namespaceObject.toPosixPath)(external_node_path_default().relative(projectRoot, tmpDirPath));
|
|
106
|
+
const remoteEntryName = (0, external_helpers_js_namespaceObject.removeExtension)(external_node_path_default().basename(remoteEntryPath));
|
|
107
|
+
const relativeRemoteEntryPath = (0, external_helpers_js_namespaceObject.toPosixPath)(external_node_path_default().relative(projectRoot, remoteEntryPath));
|
|
108
|
+
const requests = [
|
|
109
|
+
{
|
|
110
|
+
bundlePath: `${relativeTmpDirPath}/${remoteEntryName}.bundle`,
|
|
111
|
+
entryFile: `./${relativeRemoteEntryPath}`,
|
|
112
|
+
isContainer: true,
|
|
113
|
+
virtualModule: {
|
|
114
|
+
filePath: remoteEntryPath,
|
|
115
|
+
getCode: ()=>(0, external_generators_js_namespaceObject.getRemoteEntryModule)(federationConfig, {
|
|
116
|
+
projectDir: projectRoot,
|
|
117
|
+
tmpDir: tmpDirPath
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
];
|
|
122
|
+
for (const exposePath of Object.values(federationConfig.exposes)){
|
|
123
|
+
const bundlePath = getBundlePathForSource(exposePath);
|
|
124
|
+
requests.push({
|
|
125
|
+
bundlePath,
|
|
126
|
+
entryFile: normalizeEntryFile(exposePath),
|
|
127
|
+
isContainer: false
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
for (const [sharedName, sharedConfig] of Object.entries(federationConfig.shared)){
|
|
131
|
+
if (sharedConfig.eager || false === sharedConfig.import) continue;
|
|
132
|
+
const sharedVirtualModulePath = (0, external_manifest_js_namespaceObject.getSharedVirtualModulePath)(tmpDirPath, sharedName);
|
|
133
|
+
const relativeSharedVirtualModulePath = (0, external_helpers_js_namespaceObject.toPosixPath)(external_node_path_default().relative(projectRoot, sharedVirtualModulePath));
|
|
134
|
+
const sharedImportName = getSharedImportName(sharedName, sharedConfig);
|
|
135
|
+
requests.push({
|
|
136
|
+
bundlePath: (0, external_helpers_js_namespaceObject.replaceExtension)(relativeSharedVirtualModulePath, '.bundle'),
|
|
137
|
+
entryFile: normalizeEntryFile(relativeSharedVirtualModulePath),
|
|
138
|
+
isContainer: false,
|
|
139
|
+
virtualModule: {
|
|
140
|
+
filePath: sharedVirtualModulePath,
|
|
141
|
+
getCode: ()=>(0, external_generators_js_namespaceObject.getRemoteModule)(sharedImportName)
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
return requests;
|
|
146
|
+
}
|
|
147
|
+
async function ensureVirtualModuleReady(virtualModule, vmManager) {
|
|
148
|
+
const code = virtualModule.getCode();
|
|
149
|
+
await external_node_fs_namespaceObject.promises.mkdir(external_node_path_default().dirname(virtualModule.filePath), {
|
|
150
|
+
recursive: true
|
|
151
|
+
});
|
|
152
|
+
await external_node_fs_namespaceObject.promises.writeFile(virtualModule.filePath, code, 'utf-8');
|
|
153
|
+
vmManager.registerVirtualModule(virtualModule.filePath, ()=>code);
|
|
154
|
+
}
|
|
155
|
+
function getBundleOptions(request, host, warmupOptions) {
|
|
156
|
+
const query = getBundleQuery(warmupOptions, request.isContainer);
|
|
157
|
+
const sourceUrl = getSourceUrl(host, request.bundlePath, query);
|
|
158
|
+
const bundleOptions = {
|
|
159
|
+
...metro_compat_js_namespaceObject.Server.DEFAULT_BUNDLE_OPTIONS,
|
|
160
|
+
dev: warmupOptions.dev,
|
|
161
|
+
entryFile: request.entryFile,
|
|
162
|
+
excludeSource: warmupOptions.excludeSource,
|
|
163
|
+
lazy: true,
|
|
164
|
+
minify: warmupOptions.minify,
|
|
165
|
+
modulesOnly: !request.isContainer,
|
|
166
|
+
platform: warmupOptions.platform,
|
|
167
|
+
runModule: request.isContainer,
|
|
168
|
+
sourceMapUrl: sourceUrl.replace(/\.bundle(\?)/, '.map$1'),
|
|
169
|
+
sourceUrl
|
|
170
|
+
};
|
|
171
|
+
if (warmupOptions.sourcePaths) bundleOptions.sourcePaths = warmupOptions.sourcePaths;
|
|
172
|
+
return bundleOptions;
|
|
173
|
+
}
|
|
174
|
+
function getBundleQuery(warmupOptions, isContainer) {
|
|
175
|
+
const query = new URLSearchParams();
|
|
176
|
+
query.set('platform', warmupOptions.platform);
|
|
177
|
+
query.set('dev', String(warmupOptions.dev));
|
|
178
|
+
query.set('lazy', 'true');
|
|
179
|
+
query.set('minify', String(warmupOptions.minify));
|
|
180
|
+
query.set('runModule', String(isContainer));
|
|
181
|
+
query.set('modulesOnly', String(!isContainer));
|
|
182
|
+
if (warmupOptions.excludeSource) query.set('excludeSource', 'true');
|
|
183
|
+
if (warmupOptions.sourcePaths) query.set('sourcePaths', warmupOptions.sourcePaths);
|
|
184
|
+
return query;
|
|
185
|
+
}
|
|
186
|
+
function getSourceUrl(host, bundlePath, query) {
|
|
187
|
+
const normalizedBundlePath = bundlePath.startsWith('/') ? bundlePath : `/${bundlePath}`;
|
|
188
|
+
return `http://${host ?? 'localhost'}${normalizedBundlePath}?${query.toString()}`;
|
|
189
|
+
}
|
|
190
|
+
function getBundlePathForSource(sourcePath) {
|
|
191
|
+
const normalized = (0, external_helpers_js_namespaceObject.toPosixPath)(external_node_path_default().normalize(sourcePath));
|
|
192
|
+
const withoutPrefix = normalized.startsWith('./') ? normalized.slice(2) : normalized;
|
|
193
|
+
return (0, external_helpers_js_namespaceObject.replaceExtension)(withoutPrefix, '.bundle');
|
|
194
|
+
}
|
|
195
|
+
function normalizeEntryFile(sourcePath) {
|
|
196
|
+
const normalized = (0, external_helpers_js_namespaceObject.toPosixPath)(external_node_path_default().normalize(sourcePath));
|
|
197
|
+
return normalized.startsWith('./') ? normalized : `./${normalized}`;
|
|
198
|
+
}
|
|
199
|
+
function getSharedImportName(sharedName, sharedConfig) {
|
|
200
|
+
return 'string' == typeof sharedConfig.import ? sharedConfig.import : sharedName;
|
|
201
|
+
}
|
|
202
|
+
function getBoolean(params, key, defaultValue) {
|
|
203
|
+
const value = params.get(key);
|
|
204
|
+
if (null == value) return defaultValue;
|
|
205
|
+
return 'true' === value || '1' === value;
|
|
206
|
+
}
|
|
207
|
+
exports.createManifestMiddleware = __webpack_exports__.createManifestMiddleware;
|
|
208
|
+
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
209
|
+
"createManifestMiddleware"
|
|
210
|
+
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
211
|
+
Object.defineProperty(exports, '__esModule', {
|
|
212
|
+
value: true
|
|
213
|
+
});
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import 'module';
|
|
2
|
+
/*#__PURE__*/ import.meta.url;
|
|
3
|
+
import { promises } from "node:fs";
|
|
4
|
+
import node_path from "node:path";
|
|
5
|
+
import { Server } from "../utils/metro-compat.mjs";
|
|
6
|
+
import { MANIFEST_FILENAME } from "./constants.mjs";
|
|
7
|
+
import { getRemoteEntryModule, getRemoteModule } from "./generators.mjs";
|
|
8
|
+
import { removeExtension, replaceExtension, toPosixPath } from "./helpers.mjs";
|
|
9
|
+
import { getSharedVirtualModulePath } from "./manifest.mjs";
|
|
10
|
+
function createManifestMiddleware({ federationConfig, projectRoot, remoteEntryPath, tmpDirPath, vmManager }) {
|
|
11
|
+
const warmups = new Map();
|
|
12
|
+
return (middleware, metroServer)=>{
|
|
13
|
+
const nextMiddleware = middleware;
|
|
14
|
+
return async (req, res, next)=>{
|
|
15
|
+
try {
|
|
16
|
+
const warmupOptions = getManifestWarmupOptions(req.url);
|
|
17
|
+
if (warmupOptions) {
|
|
18
|
+
const warmupKey = JSON.stringify(warmupOptions);
|
|
19
|
+
let warmup = warmups.get(warmupKey);
|
|
20
|
+
if (!warmup) {
|
|
21
|
+
warmup = warmManifestBundles(metroServer, {
|
|
22
|
+
federationConfig,
|
|
23
|
+
host: req.headers.host,
|
|
24
|
+
projectRoot,
|
|
25
|
+
remoteEntryPath,
|
|
26
|
+
tmpDirPath,
|
|
27
|
+
vmManager,
|
|
28
|
+
warmupOptions
|
|
29
|
+
}).finally(()=>{
|
|
30
|
+
warmups.delete(warmupKey);
|
|
31
|
+
});
|
|
32
|
+
warmups.set(warmupKey, warmup);
|
|
33
|
+
}
|
|
34
|
+
await warmup;
|
|
35
|
+
}
|
|
36
|
+
return nextMiddleware(req, res, next);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
next(error instanceof Error ? error : new Error(String(error)));
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function getManifestWarmupOptions(rawUrl) {
|
|
44
|
+
const parsedUrl = new URL(rawUrl ?? '/', 'http://localhost');
|
|
45
|
+
if (parsedUrl.pathname !== `/${MANIFEST_FILENAME}`) return null;
|
|
46
|
+
const platform = parsedUrl.searchParams.get('platform');
|
|
47
|
+
if (!platform) return null;
|
|
48
|
+
return {
|
|
49
|
+
dev: getBoolean(parsedUrl.searchParams, 'dev', true),
|
|
50
|
+
excludeSource: getBoolean(parsedUrl.searchParams, 'excludeSource', false),
|
|
51
|
+
minify: getBoolean(parsedUrl.searchParams, 'minify', false),
|
|
52
|
+
platform,
|
|
53
|
+
sourcePaths: parsedUrl.searchParams.get('sourcePaths') ?? void 0
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
async function warmManifestBundles(metroServer, { federationConfig, host, projectRoot, remoteEntryPath, tmpDirPath, vmManager, warmupOptions }) {
|
|
57
|
+
for (const request of getBundleWarmupRequests({
|
|
58
|
+
federationConfig,
|
|
59
|
+
projectRoot,
|
|
60
|
+
remoteEntryPath,
|
|
61
|
+
tmpDirPath,
|
|
62
|
+
vmManager
|
|
63
|
+
})){
|
|
64
|
+
if (request.virtualModule) await ensureVirtualModuleReady(request.virtualModule, vmManager);
|
|
65
|
+
await metroServer.build(getBundleOptions(request, host, warmupOptions));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function getBundleWarmupRequests({ federationConfig, projectRoot, remoteEntryPath, tmpDirPath }) {
|
|
69
|
+
const relativeTmpDirPath = toPosixPath(node_path.relative(projectRoot, tmpDirPath));
|
|
70
|
+
const remoteEntryName = removeExtension(node_path.basename(remoteEntryPath));
|
|
71
|
+
const relativeRemoteEntryPath = toPosixPath(node_path.relative(projectRoot, remoteEntryPath));
|
|
72
|
+
const requests = [
|
|
73
|
+
{
|
|
74
|
+
bundlePath: `${relativeTmpDirPath}/${remoteEntryName}.bundle`,
|
|
75
|
+
entryFile: `./${relativeRemoteEntryPath}`,
|
|
76
|
+
isContainer: true,
|
|
77
|
+
virtualModule: {
|
|
78
|
+
filePath: remoteEntryPath,
|
|
79
|
+
getCode: ()=>getRemoteEntryModule(federationConfig, {
|
|
80
|
+
projectDir: projectRoot,
|
|
81
|
+
tmpDir: tmpDirPath
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
];
|
|
86
|
+
for (const exposePath of Object.values(federationConfig.exposes)){
|
|
87
|
+
const bundlePath = getBundlePathForSource(exposePath);
|
|
88
|
+
requests.push({
|
|
89
|
+
bundlePath,
|
|
90
|
+
entryFile: normalizeEntryFile(exposePath),
|
|
91
|
+
isContainer: false
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
for (const [sharedName, sharedConfig] of Object.entries(federationConfig.shared)){
|
|
95
|
+
if (sharedConfig.eager || false === sharedConfig.import) continue;
|
|
96
|
+
const sharedVirtualModulePath = getSharedVirtualModulePath(tmpDirPath, sharedName);
|
|
97
|
+
const relativeSharedVirtualModulePath = toPosixPath(node_path.relative(projectRoot, sharedVirtualModulePath));
|
|
98
|
+
const sharedImportName = getSharedImportName(sharedName, sharedConfig);
|
|
99
|
+
requests.push({
|
|
100
|
+
bundlePath: replaceExtension(relativeSharedVirtualModulePath, '.bundle'),
|
|
101
|
+
entryFile: normalizeEntryFile(relativeSharedVirtualModulePath),
|
|
102
|
+
isContainer: false,
|
|
103
|
+
virtualModule: {
|
|
104
|
+
filePath: sharedVirtualModulePath,
|
|
105
|
+
getCode: ()=>getRemoteModule(sharedImportName)
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return requests;
|
|
110
|
+
}
|
|
111
|
+
async function ensureVirtualModuleReady(virtualModule, vmManager) {
|
|
112
|
+
const code = virtualModule.getCode();
|
|
113
|
+
await promises.mkdir(node_path.dirname(virtualModule.filePath), {
|
|
114
|
+
recursive: true
|
|
115
|
+
});
|
|
116
|
+
await promises.writeFile(virtualModule.filePath, code, 'utf-8');
|
|
117
|
+
vmManager.registerVirtualModule(virtualModule.filePath, ()=>code);
|
|
118
|
+
}
|
|
119
|
+
function getBundleOptions(request, host, warmupOptions) {
|
|
120
|
+
const query = getBundleQuery(warmupOptions, request.isContainer);
|
|
121
|
+
const sourceUrl = getSourceUrl(host, request.bundlePath, query);
|
|
122
|
+
const bundleOptions = {
|
|
123
|
+
...Server.DEFAULT_BUNDLE_OPTIONS,
|
|
124
|
+
dev: warmupOptions.dev,
|
|
125
|
+
entryFile: request.entryFile,
|
|
126
|
+
excludeSource: warmupOptions.excludeSource,
|
|
127
|
+
lazy: true,
|
|
128
|
+
minify: warmupOptions.minify,
|
|
129
|
+
modulesOnly: !request.isContainer,
|
|
130
|
+
platform: warmupOptions.platform,
|
|
131
|
+
runModule: request.isContainer,
|
|
132
|
+
sourceMapUrl: sourceUrl.replace(/\.bundle(\?)/, '.map$1'),
|
|
133
|
+
sourceUrl
|
|
134
|
+
};
|
|
135
|
+
if (warmupOptions.sourcePaths) bundleOptions.sourcePaths = warmupOptions.sourcePaths;
|
|
136
|
+
return bundleOptions;
|
|
137
|
+
}
|
|
138
|
+
function getBundleQuery(warmupOptions, isContainer) {
|
|
139
|
+
const query = new URLSearchParams();
|
|
140
|
+
query.set('platform', warmupOptions.platform);
|
|
141
|
+
query.set('dev', String(warmupOptions.dev));
|
|
142
|
+
query.set('lazy', 'true');
|
|
143
|
+
query.set('minify', String(warmupOptions.minify));
|
|
144
|
+
query.set('runModule', String(isContainer));
|
|
145
|
+
query.set('modulesOnly', String(!isContainer));
|
|
146
|
+
if (warmupOptions.excludeSource) query.set('excludeSource', 'true');
|
|
147
|
+
if (warmupOptions.sourcePaths) query.set('sourcePaths', warmupOptions.sourcePaths);
|
|
148
|
+
return query;
|
|
149
|
+
}
|
|
150
|
+
function getSourceUrl(host, bundlePath, query) {
|
|
151
|
+
const normalizedBundlePath = bundlePath.startsWith('/') ? bundlePath : `/${bundlePath}`;
|
|
152
|
+
return `http://${host ?? 'localhost'}${normalizedBundlePath}?${query.toString()}`;
|
|
153
|
+
}
|
|
154
|
+
function getBundlePathForSource(sourcePath) {
|
|
155
|
+
const normalized = toPosixPath(node_path.normalize(sourcePath));
|
|
156
|
+
const withoutPrefix = normalized.startsWith('./') ? normalized.slice(2) : normalized;
|
|
157
|
+
return replaceExtension(withoutPrefix, '.bundle');
|
|
158
|
+
}
|
|
159
|
+
function normalizeEntryFile(sourcePath) {
|
|
160
|
+
const normalized = toPosixPath(node_path.normalize(sourcePath));
|
|
161
|
+
return normalized.startsWith('./') ? normalized : `./${normalized}`;
|
|
162
|
+
}
|
|
163
|
+
function getSharedImportName(sharedName, sharedConfig) {
|
|
164
|
+
return 'string' == typeof sharedConfig.import ? sharedConfig.import : sharedName;
|
|
165
|
+
}
|
|
166
|
+
function getBoolean(params, key, defaultValue) {
|
|
167
|
+
const value = params.get(key);
|
|
168
|
+
if (null == value) return defaultValue;
|
|
169
|
+
return 'true' === value || '1' === value;
|
|
170
|
+
}
|
|
171
|
+
export { createManifestMiddleware };
|
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
import type { ModuleFederationConfigNormalized } from '../types';
|
|
2
|
-
export
|
|
3
|
-
export
|
|
2
|
+
export type BundleHashMap = Map<string, string>;
|
|
3
|
+
export type ManifestGenerationOptions = {
|
|
4
|
+
projectRoot?: string;
|
|
5
|
+
target?: 'development' | 'build';
|
|
6
|
+
tmpDirPath?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function createManifest(options: ModuleFederationConfigNormalized, mfMetroPath: string, hashesOrOptions?: BundleHashMap | ManifestGenerationOptions, manifestOptions?: ManifestGenerationOptions): string;
|
|
9
|
+
export declare function updateManifest(manifestPath: string, options: ModuleFederationConfigNormalized, hashesOrOptions?: BundleHashMap | ManifestGenerationOptions, manifestOptions?: ManifestGenerationOptions): string;
|
|
10
|
+
/**
|
|
11
|
+
* Compute SHA-256 of bundle code and store the hash for the matching
|
|
12
|
+
* manifest entry (container, exposed, or shared).
|
|
13
|
+
*/
|
|
14
|
+
export declare function recordBundleHash(hashes: BundleHashMap, code: string, entryPoint: string, projectRoot: string, config: ModuleFederationConfigNormalized): void;
|
|
15
|
+
export declare function getSharedVirtualModuleName(sharedName: string): string;
|
|
16
|
+
export declare function getSharedVirtualModulePath(tmpDirPath: string, sharedName: string): string;
|
package/dist/plugin/manifest.js
CHANGED
|
@@ -33,42 +33,62 @@ var __webpack_require__ = {};
|
|
|
33
33
|
var __webpack_exports__ = {};
|
|
34
34
|
__webpack_require__.r(__webpack_exports__);
|
|
35
35
|
__webpack_require__.d(__webpack_exports__, {
|
|
36
|
+
getSharedVirtualModulePath: ()=>getSharedVirtualModulePath,
|
|
36
37
|
createManifest: ()=>createManifest,
|
|
37
|
-
|
|
38
|
+
recordBundleHash: ()=>recordBundleHash,
|
|
39
|
+
updateManifest: ()=>updateManifest,
|
|
40
|
+
getSharedVirtualModuleName: ()=>getSharedVirtualModuleName
|
|
38
41
|
});
|
|
42
|
+
const external_node_crypto_namespaceObject = require("node:crypto");
|
|
43
|
+
var external_node_crypto_default = /*#__PURE__*/ __webpack_require__.n(external_node_crypto_namespaceObject);
|
|
39
44
|
const external_node_fs_namespaceObject = require("node:fs");
|
|
40
45
|
var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
|
|
41
46
|
const external_node_path_namespaceObject = require("node:path");
|
|
42
47
|
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
43
48
|
const external_constants_js_namespaceObject = require("./constants.js");
|
|
44
|
-
|
|
49
|
+
const external_helpers_js_namespaceObject = require("./helpers.js");
|
|
50
|
+
function createManifest(options, mfMetroPath, hashesOrOptions, manifestOptions) {
|
|
51
|
+
const { hashes, options: generationOptions } = normalizeManifestArgs(hashesOrOptions, manifestOptions);
|
|
45
52
|
const manifestPath = external_node_path_default().join(mfMetroPath, external_constants_js_namespaceObject.MANIFEST_FILENAME);
|
|
46
|
-
const manifest = generateManifest(options);
|
|
53
|
+
const manifest = generateManifest(options, hashes, generationOptions);
|
|
47
54
|
external_node_fs_default().writeFileSync(manifestPath, JSON.stringify(manifest, void 0, 2));
|
|
48
55
|
return manifestPath;
|
|
49
56
|
}
|
|
50
|
-
|
|
51
|
-
|
|
57
|
+
function updateManifest(manifestPath, options, hashesOrOptions, manifestOptions) {
|
|
58
|
+
var _existingManifest_metaData;
|
|
59
|
+
const { hashes, options: generationOptions } = normalizeManifestArgs(hashesOrOptions, manifestOptions);
|
|
60
|
+
const manifest = generateManifest(options, hashes, generationOptions);
|
|
61
|
+
const existingManifest = readManifest(manifestPath);
|
|
62
|
+
if (null == existingManifest ? void 0 : null == (_existingManifest_metaData = existingManifest.metaData) ? void 0 : _existingManifest_metaData.types) manifest.metaData.types = {
|
|
63
|
+
...manifest.metaData.types,
|
|
64
|
+
...existingManifest.metaData.types
|
|
65
|
+
};
|
|
52
66
|
external_node_fs_default().writeFileSync(manifestPath, JSON.stringify(manifest, void 0, 2));
|
|
53
67
|
return manifestPath;
|
|
54
|
-
}
|
|
55
|
-
function
|
|
68
|
+
}
|
|
69
|
+
function recordBundleHash(hashes, code, entryPoint, projectRoot, config) {
|
|
70
|
+
const hash = external_node_crypto_default().createHash('sha256').update(code).digest('hex');
|
|
71
|
+
const key = resolveBundleKey(entryPoint, projectRoot, config);
|
|
72
|
+
if (key) hashes.set(key, hash);
|
|
73
|
+
}
|
|
74
|
+
function generateManifest(config, hashes, manifestOptions = {}) {
|
|
56
75
|
return {
|
|
57
76
|
id: config.name,
|
|
58
77
|
name: config.name,
|
|
59
|
-
metaData: generateMetaData(config),
|
|
60
|
-
exposes: generateExposes(config),
|
|
78
|
+
metaData: generateMetaData(config, hashes),
|
|
79
|
+
exposes: generateExposes(config, hashes),
|
|
61
80
|
remotes: generateRemotes(config),
|
|
62
|
-
shared: generateShared(config)
|
|
81
|
+
shared: generateShared(config, hashes, manifestOptions)
|
|
63
82
|
};
|
|
64
83
|
}
|
|
65
|
-
function generateMetaData(config) {
|
|
84
|
+
function generateMetaData(config, hashes) {
|
|
66
85
|
return {
|
|
67
86
|
name: config.name,
|
|
68
87
|
type: 'app',
|
|
69
88
|
buildInfo: {
|
|
70
89
|
buildVersion: '1.0.0',
|
|
71
|
-
buildName: config.name
|
|
90
|
+
buildName: config.name,
|
|
91
|
+
hash: (null == hashes ? void 0 : hashes.get(`container:${config.name}`)) ?? ''
|
|
72
92
|
},
|
|
73
93
|
remoteEntry: {
|
|
74
94
|
name: config.filename,
|
|
@@ -86,7 +106,7 @@ function generateMetaData(config) {
|
|
|
86
106
|
publicPath: 'auto'
|
|
87
107
|
};
|
|
88
108
|
}
|
|
89
|
-
function generateExposes(config) {
|
|
109
|
+
function generateExposes(config, hashes) {
|
|
90
110
|
return Object.keys(config.exposes).map((expose)=>{
|
|
91
111
|
const formatKey = expose.replace('./', '');
|
|
92
112
|
const assets = getEmptyAssets();
|
|
@@ -95,7 +115,8 @@ function generateExposes(config) {
|
|
|
95
115
|
id: `${config.name}:${formatKey}`,
|
|
96
116
|
name: formatKey,
|
|
97
117
|
path: expose,
|
|
98
|
-
assets
|
|
118
|
+
assets,
|
|
119
|
+
hash: (null == hashes ? void 0 : hashes.get(`expose:${formatKey}`)) ?? ''
|
|
99
120
|
};
|
|
100
121
|
});
|
|
101
122
|
}
|
|
@@ -107,22 +128,86 @@ function generateRemotes(config) {
|
|
|
107
128
|
entry: '*'
|
|
108
129
|
}));
|
|
109
130
|
}
|
|
110
|
-
function generateShared(config) {
|
|
131
|
+
function generateShared(config, hashes, manifestOptions = {}) {
|
|
111
132
|
return Object.keys(config.shared).map((sharedName)=>{
|
|
112
133
|
const assets = getEmptyAssets();
|
|
113
134
|
if (config.shared[sharedName].eager) assets.js.sync.push(config.filename);
|
|
114
|
-
else if (false !== config.shared[sharedName].import) assets.js.sync.push(
|
|
135
|
+
else if (false !== config.shared[sharedName].import) assets.js.sync.push(getSharedAssetPath(sharedName, manifestOptions));
|
|
115
136
|
return {
|
|
116
137
|
id: sharedName,
|
|
117
138
|
name: sharedName,
|
|
118
139
|
version: getManifestVersion(config.shared[sharedName].version),
|
|
119
140
|
requiredVersion: getManifestRequiredVersion(config.shared[sharedName].requiredVersion),
|
|
120
141
|
singleton: config.shared[sharedName].singleton,
|
|
121
|
-
hash: '',
|
|
142
|
+
hash: (null == hashes ? void 0 : hashes.get(`shared:${sharedName}`)) ?? '',
|
|
122
143
|
assets
|
|
123
144
|
};
|
|
124
145
|
});
|
|
125
146
|
}
|
|
147
|
+
function resolveBundleKey(entryPoint, projectRoot, config) {
|
|
148
|
+
const relPath = (0, external_helpers_js_namespaceObject.toPosixPath)(external_node_path_default().relative(projectRoot, entryPoint));
|
|
149
|
+
const normalizedRel = relPath.startsWith('./') ? relPath.slice(2) : relPath;
|
|
150
|
+
const normalizedRelNoExt = (0, external_helpers_js_namespaceObject.removeExtension)(normalizedRel);
|
|
151
|
+
for (const [exposeKey, exposePath] of Object.entries(config.exposes)){
|
|
152
|
+
const normalizedExpose = (0, external_helpers_js_namespaceObject.toPosixPath)(exposePath.startsWith('./') ? exposePath.slice(2) : exposePath);
|
|
153
|
+
if (normalizedRel === normalizedExpose || normalizedRelNoExt === (0, external_helpers_js_namespaceObject.removeExtension)(normalizedExpose)) return `expose:${exposeKey.replace('./', '')}`;
|
|
154
|
+
}
|
|
155
|
+
if ((0, external_helpers_js_namespaceObject.removeExtension)(external_node_path_default().basename(entryPoint)) === (0, external_helpers_js_namespaceObject.removeExtension)(external_node_path_default().basename(config.filename))) return `container:${config.name}`;
|
|
156
|
+
const virtualSharedKey = resolveDevVirtualSharedKey(entryPoint, projectRoot, config);
|
|
157
|
+
if (virtualSharedKey) return virtualSharedKey;
|
|
158
|
+
const absPath = (0, external_helpers_js_namespaceObject.toPosixPath)(external_node_path_default().resolve(entryPoint));
|
|
159
|
+
const nmMatch = absPath.match(/.*node_modules\/(.+)/);
|
|
160
|
+
if (nmMatch) {
|
|
161
|
+
const modulePath = (0, external_helpers_js_namespaceObject.removeExtension)(nmMatch[1]);
|
|
162
|
+
const sharedKey = findSharedKeyForModulePath(modulePath, config);
|
|
163
|
+
if (sharedKey) return `shared:${sharedKey}`;
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
function normalizeManifestArgs(hashesOrOptions, manifestOptions) {
|
|
168
|
+
if (hashesOrOptions instanceof Map) return {
|
|
169
|
+
hashes: hashesOrOptions,
|
|
170
|
+
options: manifestOptions ?? {}
|
|
171
|
+
};
|
|
172
|
+
return {
|
|
173
|
+
hashes: void 0,
|
|
174
|
+
options: hashesOrOptions ?? {}
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function readManifest(manifestPath) {
|
|
178
|
+
if (!external_node_fs_default().existsSync(manifestPath)) return;
|
|
179
|
+
return JSON.parse(external_node_fs_default().readFileSync(manifestPath, 'utf-8'));
|
|
180
|
+
}
|
|
181
|
+
function getSharedVirtualModuleName(sharedName) {
|
|
182
|
+
return sharedName.replaceAll('/', '_');
|
|
183
|
+
}
|
|
184
|
+
function getSharedVirtualModulePath(tmpDirPath, sharedName) {
|
|
185
|
+
return external_node_path_default().join(tmpDirPath, 'shared', `${getSharedVirtualModuleName(sharedName)}.js`);
|
|
186
|
+
}
|
|
187
|
+
function getSharedAssetPath(sharedName, manifestOptions) {
|
|
188
|
+
if ('development' === manifestOptions.target && manifestOptions.projectRoot && manifestOptions.tmpDirPath) return (0, external_helpers_js_namespaceObject.toPosixPath)(external_node_path_default().relative(manifestOptions.projectRoot, getSharedVirtualModulePath(manifestOptions.tmpDirPath, sharedName)));
|
|
189
|
+
return `shared/${sharedName}.bundle`;
|
|
190
|
+
}
|
|
191
|
+
function resolveDevVirtualSharedKey(entryPoint, projectRoot, config) {
|
|
192
|
+
const relativePath = (0, external_helpers_js_namespaceObject.toPosixPath)(external_node_path_default().relative(projectRoot, entryPoint));
|
|
193
|
+
const virtualSharedPrefix = `node_modules/${external_constants_js_namespaceObject.TMP_DIR_NAME}/shared/`;
|
|
194
|
+
if (!relativePath.startsWith(virtualSharedPrefix)) return null;
|
|
195
|
+
const virtualModuleName = (0, external_helpers_js_namespaceObject.removeExtension)(relativePath.slice(virtualSharedPrefix.length));
|
|
196
|
+
const sharedKey = Object.keys(config.shared).find((sharedName)=>getSharedVirtualModuleName(sharedName) === virtualModuleName);
|
|
197
|
+
return sharedKey ? `shared:${sharedKey}` : null;
|
|
198
|
+
}
|
|
199
|
+
function findSharedKeyForModulePath(modulePath, config) {
|
|
200
|
+
const sharedEntries = Object.entries(config.shared).map(([sharedName, sharedConfig])=>{
|
|
201
|
+
const importName = 'string' == typeof sharedConfig.import ? sharedConfig.import : sharedName;
|
|
202
|
+
return {
|
|
203
|
+
importName,
|
|
204
|
+
sharedName
|
|
205
|
+
};
|
|
206
|
+
}).sort((a, b)=>b.importName.length - a.importName.length);
|
|
207
|
+
const normalizedModulePath = (0, external_helpers_js_namespaceObject.toPosixPath)(modulePath);
|
|
208
|
+
for (const { importName, sharedName } of sharedEntries)if (normalizedModulePath === importName || normalizedModulePath.startsWith(`${importName}/`)) return sharedName;
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
126
211
|
function getManifestVersion(version) {
|
|
127
212
|
return 'string' == typeof version ? version : '';
|
|
128
213
|
}
|
|
@@ -142,9 +227,15 @@ function getEmptyAssets() {
|
|
|
142
227
|
};
|
|
143
228
|
}
|
|
144
229
|
exports.createManifest = __webpack_exports__.createManifest;
|
|
230
|
+
exports.getSharedVirtualModuleName = __webpack_exports__.getSharedVirtualModuleName;
|
|
231
|
+
exports.getSharedVirtualModulePath = __webpack_exports__.getSharedVirtualModulePath;
|
|
232
|
+
exports.recordBundleHash = __webpack_exports__.recordBundleHash;
|
|
145
233
|
exports.updateManifest = __webpack_exports__.updateManifest;
|
|
146
234
|
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
147
235
|
"createManifest",
|
|
236
|
+
"getSharedVirtualModuleName",
|
|
237
|
+
"getSharedVirtualModulePath",
|
|
238
|
+
"recordBundleHash",
|
|
148
239
|
"updateManifest"
|
|
149
240
|
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
150
241
|
Object.defineProperty(exports, '__esModule', {
|
package/dist/plugin/manifest.mjs
CHANGED
|
@@ -1,36 +1,52 @@
|
|
|
1
1
|
import 'module';
|
|
2
2
|
/*#__PURE__*/ import.meta.url;
|
|
3
|
+
import node_crypto from "node:crypto";
|
|
3
4
|
import node_fs from "node:fs";
|
|
4
5
|
import node_path from "node:path";
|
|
5
|
-
import { MANIFEST_FILENAME } from "./constants.mjs";
|
|
6
|
-
|
|
6
|
+
import { MANIFEST_FILENAME, TMP_DIR_NAME } from "./constants.mjs";
|
|
7
|
+
import { removeExtension, toPosixPath } from "./helpers.mjs";
|
|
8
|
+
function createManifest(options, mfMetroPath, hashesOrOptions, manifestOptions) {
|
|
9
|
+
const { hashes, options: generationOptions } = normalizeManifestArgs(hashesOrOptions, manifestOptions);
|
|
7
10
|
const manifestPath = node_path.join(mfMetroPath, MANIFEST_FILENAME);
|
|
8
|
-
const manifest = generateManifest(options);
|
|
11
|
+
const manifest = generateManifest(options, hashes, generationOptions);
|
|
9
12
|
node_fs.writeFileSync(manifestPath, JSON.stringify(manifest, void 0, 2));
|
|
10
13
|
return manifestPath;
|
|
11
14
|
}
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
function updateManifest(manifestPath, options, hashesOrOptions, manifestOptions) {
|
|
16
|
+
var _existingManifest_metaData;
|
|
17
|
+
const { hashes, options: generationOptions } = normalizeManifestArgs(hashesOrOptions, manifestOptions);
|
|
18
|
+
const manifest = generateManifest(options, hashes, generationOptions);
|
|
19
|
+
const existingManifest = readManifest(manifestPath);
|
|
20
|
+
if (null == existingManifest ? void 0 : null == (_existingManifest_metaData = existingManifest.metaData) ? void 0 : _existingManifest_metaData.types) manifest.metaData.types = {
|
|
21
|
+
...manifest.metaData.types,
|
|
22
|
+
...existingManifest.metaData.types
|
|
23
|
+
};
|
|
14
24
|
node_fs.writeFileSync(manifestPath, JSON.stringify(manifest, void 0, 2));
|
|
15
25
|
return manifestPath;
|
|
16
|
-
}
|
|
17
|
-
function
|
|
26
|
+
}
|
|
27
|
+
function recordBundleHash(hashes, code, entryPoint, projectRoot, config) {
|
|
28
|
+
const hash = node_crypto.createHash('sha256').update(code).digest('hex');
|
|
29
|
+
const key = resolveBundleKey(entryPoint, projectRoot, config);
|
|
30
|
+
if (key) hashes.set(key, hash);
|
|
31
|
+
}
|
|
32
|
+
function generateManifest(config, hashes, manifestOptions = {}) {
|
|
18
33
|
return {
|
|
19
34
|
id: config.name,
|
|
20
35
|
name: config.name,
|
|
21
|
-
metaData: generateMetaData(config),
|
|
22
|
-
exposes: generateExposes(config),
|
|
36
|
+
metaData: generateMetaData(config, hashes),
|
|
37
|
+
exposes: generateExposes(config, hashes),
|
|
23
38
|
remotes: generateRemotes(config),
|
|
24
|
-
shared: generateShared(config)
|
|
39
|
+
shared: generateShared(config, hashes, manifestOptions)
|
|
25
40
|
};
|
|
26
41
|
}
|
|
27
|
-
function generateMetaData(config) {
|
|
42
|
+
function generateMetaData(config, hashes) {
|
|
28
43
|
return {
|
|
29
44
|
name: config.name,
|
|
30
45
|
type: 'app',
|
|
31
46
|
buildInfo: {
|
|
32
47
|
buildVersion: '1.0.0',
|
|
33
|
-
buildName: config.name
|
|
48
|
+
buildName: config.name,
|
|
49
|
+
hash: (null == hashes ? void 0 : hashes.get(`container:${config.name}`)) ?? ''
|
|
34
50
|
},
|
|
35
51
|
remoteEntry: {
|
|
36
52
|
name: config.filename,
|
|
@@ -48,7 +64,7 @@ function generateMetaData(config) {
|
|
|
48
64
|
publicPath: 'auto'
|
|
49
65
|
};
|
|
50
66
|
}
|
|
51
|
-
function generateExposes(config) {
|
|
67
|
+
function generateExposes(config, hashes) {
|
|
52
68
|
return Object.keys(config.exposes).map((expose)=>{
|
|
53
69
|
const formatKey = expose.replace('./', '');
|
|
54
70
|
const assets = getEmptyAssets();
|
|
@@ -57,7 +73,8 @@ function generateExposes(config) {
|
|
|
57
73
|
id: `${config.name}:${formatKey}`,
|
|
58
74
|
name: formatKey,
|
|
59
75
|
path: expose,
|
|
60
|
-
assets
|
|
76
|
+
assets,
|
|
77
|
+
hash: (null == hashes ? void 0 : hashes.get(`expose:${formatKey}`)) ?? ''
|
|
61
78
|
};
|
|
62
79
|
});
|
|
63
80
|
}
|
|
@@ -69,22 +86,86 @@ function generateRemotes(config) {
|
|
|
69
86
|
entry: '*'
|
|
70
87
|
}));
|
|
71
88
|
}
|
|
72
|
-
function generateShared(config) {
|
|
89
|
+
function generateShared(config, hashes, manifestOptions = {}) {
|
|
73
90
|
return Object.keys(config.shared).map((sharedName)=>{
|
|
74
91
|
const assets = getEmptyAssets();
|
|
75
92
|
if (config.shared[sharedName].eager) assets.js.sync.push(config.filename);
|
|
76
|
-
else if (false !== config.shared[sharedName].import) assets.js.sync.push(
|
|
93
|
+
else if (false !== config.shared[sharedName].import) assets.js.sync.push(getSharedAssetPath(sharedName, manifestOptions));
|
|
77
94
|
return {
|
|
78
95
|
id: sharedName,
|
|
79
96
|
name: sharedName,
|
|
80
97
|
version: getManifestVersion(config.shared[sharedName].version),
|
|
81
98
|
requiredVersion: getManifestRequiredVersion(config.shared[sharedName].requiredVersion),
|
|
82
99
|
singleton: config.shared[sharedName].singleton,
|
|
83
|
-
hash: '',
|
|
100
|
+
hash: (null == hashes ? void 0 : hashes.get(`shared:${sharedName}`)) ?? '',
|
|
84
101
|
assets
|
|
85
102
|
};
|
|
86
103
|
});
|
|
87
104
|
}
|
|
105
|
+
function resolveBundleKey(entryPoint, projectRoot, config) {
|
|
106
|
+
const relPath = toPosixPath(node_path.relative(projectRoot, entryPoint));
|
|
107
|
+
const normalizedRel = relPath.startsWith('./') ? relPath.slice(2) : relPath;
|
|
108
|
+
const normalizedRelNoExt = removeExtension(normalizedRel);
|
|
109
|
+
for (const [exposeKey, exposePath] of Object.entries(config.exposes)){
|
|
110
|
+
const normalizedExpose = toPosixPath(exposePath.startsWith('./') ? exposePath.slice(2) : exposePath);
|
|
111
|
+
if (normalizedRel === normalizedExpose || normalizedRelNoExt === removeExtension(normalizedExpose)) return `expose:${exposeKey.replace('./', '')}`;
|
|
112
|
+
}
|
|
113
|
+
if (removeExtension(node_path.basename(entryPoint)) === removeExtension(node_path.basename(config.filename))) return `container:${config.name}`;
|
|
114
|
+
const virtualSharedKey = resolveDevVirtualSharedKey(entryPoint, projectRoot, config);
|
|
115
|
+
if (virtualSharedKey) return virtualSharedKey;
|
|
116
|
+
const absPath = toPosixPath(node_path.resolve(entryPoint));
|
|
117
|
+
const nmMatch = absPath.match(/.*node_modules\/(.+)/);
|
|
118
|
+
if (nmMatch) {
|
|
119
|
+
const modulePath = removeExtension(nmMatch[1]);
|
|
120
|
+
const sharedKey = findSharedKeyForModulePath(modulePath, config);
|
|
121
|
+
if (sharedKey) return `shared:${sharedKey}`;
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
function normalizeManifestArgs(hashesOrOptions, manifestOptions) {
|
|
126
|
+
if (hashesOrOptions instanceof Map) return {
|
|
127
|
+
hashes: hashesOrOptions,
|
|
128
|
+
options: manifestOptions ?? {}
|
|
129
|
+
};
|
|
130
|
+
return {
|
|
131
|
+
hashes: void 0,
|
|
132
|
+
options: hashesOrOptions ?? {}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function readManifest(manifestPath) {
|
|
136
|
+
if (!node_fs.existsSync(manifestPath)) return;
|
|
137
|
+
return JSON.parse(node_fs.readFileSync(manifestPath, 'utf-8'));
|
|
138
|
+
}
|
|
139
|
+
function getSharedVirtualModuleName(sharedName) {
|
|
140
|
+
return sharedName.replaceAll('/', '_');
|
|
141
|
+
}
|
|
142
|
+
function getSharedVirtualModulePath(tmpDirPath, sharedName) {
|
|
143
|
+
return node_path.join(tmpDirPath, 'shared', `${getSharedVirtualModuleName(sharedName)}.js`);
|
|
144
|
+
}
|
|
145
|
+
function getSharedAssetPath(sharedName, manifestOptions) {
|
|
146
|
+
if ('development' === manifestOptions.target && manifestOptions.projectRoot && manifestOptions.tmpDirPath) return toPosixPath(node_path.relative(manifestOptions.projectRoot, getSharedVirtualModulePath(manifestOptions.tmpDirPath, sharedName)));
|
|
147
|
+
return `shared/${sharedName}.bundle`;
|
|
148
|
+
}
|
|
149
|
+
function resolveDevVirtualSharedKey(entryPoint, projectRoot, config) {
|
|
150
|
+
const relativePath = toPosixPath(node_path.relative(projectRoot, entryPoint));
|
|
151
|
+
const virtualSharedPrefix = `node_modules/${TMP_DIR_NAME}/shared/`;
|
|
152
|
+
if (!relativePath.startsWith(virtualSharedPrefix)) return null;
|
|
153
|
+
const virtualModuleName = removeExtension(relativePath.slice(virtualSharedPrefix.length));
|
|
154
|
+
const sharedKey = Object.keys(config.shared).find((sharedName)=>getSharedVirtualModuleName(sharedName) === virtualModuleName);
|
|
155
|
+
return sharedKey ? `shared:${sharedKey}` : null;
|
|
156
|
+
}
|
|
157
|
+
function findSharedKeyForModulePath(modulePath, config) {
|
|
158
|
+
const sharedEntries = Object.entries(config.shared).map(([sharedName, sharedConfig])=>{
|
|
159
|
+
const importName = 'string' == typeof sharedConfig.import ? sharedConfig.import : sharedName;
|
|
160
|
+
return {
|
|
161
|
+
importName,
|
|
162
|
+
sharedName
|
|
163
|
+
};
|
|
164
|
+
}).sort((a, b)=>b.importName.length - a.importName.length);
|
|
165
|
+
const normalizedModulePath = toPosixPath(modulePath);
|
|
166
|
+
for (const { importName, sharedName } of sharedEntries)if (normalizedModulePath === importName || normalizedModulePath.startsWith(`${importName}/`)) return sharedName;
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
88
169
|
function getManifestVersion(version) {
|
|
89
170
|
return 'string' == typeof version ? version : '';
|
|
90
171
|
}
|
|
@@ -103,4 +184,4 @@ function getEmptyAssets() {
|
|
|
103
184
|
}
|
|
104
185
|
};
|
|
105
186
|
}
|
|
106
|
-
export { createManifest, updateManifest };
|
|
187
|
+
export { createManifest, getSharedVirtualModuleName, getSharedVirtualModulePath, recordBundleHash, updateManifest };
|
|
@@ -19,7 +19,7 @@ interface CreateResolveRequestOptions {
|
|
|
19
19
|
tmpDir: string;
|
|
20
20
|
};
|
|
21
21
|
options: ModuleFederationConfigNormalized;
|
|
22
|
-
vmManager: VirtualModuleManager
|
|
22
|
+
vmManager: Pick<VirtualModuleManager, 'registerVirtualModule'>;
|
|
23
23
|
customResolver?: CustomResolver;
|
|
24
24
|
}
|
|
25
25
|
export declare function createResolveRequest({ vmManager, options, hacks, paths, isRemote, customResolver, }: CreateResolveRequestOptions): CustomResolver;
|
package/dist/plugin/resolver.js
CHANGED
|
@@ -128,8 +128,8 @@ function createResolveRequest({ vmManager, options, hacks, paths, isRemote, cust
|
|
|
128
128
|
for (const sharedName of Object.keys(options.shared)){
|
|
129
129
|
const importName = options.shared[sharedName].import || sharedName;
|
|
130
130
|
if (moduleName === importName) {
|
|
131
|
-
const sharedPath = getSharedPath(
|
|
132
|
-
const sharedGenerator = ()=>(0, external_generators_js_namespaceObject.getRemoteModule)(
|
|
131
|
+
const sharedPath = getSharedPath(sharedName, paths.tmpDir);
|
|
132
|
+
const sharedGenerator = ()=>(0, external_generators_js_namespaceObject.getRemoteModule)(importName);
|
|
133
133
|
vmManager.registerVirtualModule(sharedPath, sharedGenerator);
|
|
134
134
|
return {
|
|
135
135
|
type: 'sourceFile',
|
package/dist/plugin/resolver.mjs
CHANGED
|
@@ -95,8 +95,8 @@ function createResolveRequest({ vmManager, options, hacks, paths, isRemote, cust
|
|
|
95
95
|
for (const sharedName of Object.keys(options.shared)){
|
|
96
96
|
const importName = options.shared[sharedName].import || sharedName;
|
|
97
97
|
if (moduleName === importName) {
|
|
98
|
-
const sharedPath = getSharedPath(
|
|
99
|
-
const sharedGenerator = ()=>getRemoteModule(
|
|
98
|
+
const sharedPath = getSharedPath(sharedName, paths.tmpDir);
|
|
99
|
+
const sharedGenerator = ()=>getRemoteModule(importName);
|
|
100
100
|
vmManager.registerVirtualModule(sharedPath, sharedGenerator);
|
|
101
101
|
return {
|
|
102
102
|
type: 'sourceFile',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SerializerConfigT } from 'metro-config';
|
|
2
2
|
import type { ModuleFederationConfigNormalized } from '../types';
|
|
3
|
+
import { type ManifestGenerationOptions } from './manifest';
|
|
3
4
|
type CustomSerializer = SerializerConfigT['customSerializer'];
|
|
4
|
-
export declare function getModuleFederationSerializer(mfConfig: ModuleFederationConfigNormalized, isUsingMFBundleCommand: boolean): CustomSerializer;
|
|
5
|
+
export declare function getModuleFederationSerializer(mfConfig: ModuleFederationConfigNormalized, isUsingMFBundleCommand: boolean, manifestPath?: string, manifestOptions?: ManifestGenerationOptions): CustomSerializer;
|
|
5
6
|
export {};
|
|
@@ -39,31 +39,39 @@ const external_node_path_namespaceObject = require("node:path");
|
|
|
39
39
|
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
40
40
|
const errors_js_namespaceObject = require("../utils/errors.js");
|
|
41
41
|
const external_helpers_js_namespaceObject = require("./helpers.js");
|
|
42
|
+
const external_manifest_js_namespaceObject = require("./manifest.js");
|
|
42
43
|
const metro_compat_js_namespaceObject = require("../utils/metro-compat.js");
|
|
43
|
-
function getModuleFederationSerializer(mfConfig, isUsingMFBundleCommand) {
|
|
44
|
+
function getModuleFederationSerializer(mfConfig, isUsingMFBundleCommand, manifestPath, manifestOptions) {
|
|
45
|
+
const bundleHashes = new Map();
|
|
44
46
|
return async (entryPoint, preModules, graph, options)=>{
|
|
45
47
|
const syncRemoteModules = collectSyncRemoteModules(graph, mfConfig.remotes);
|
|
46
48
|
const syncSharedModules = collectSyncSharedModules(graph, mfConfig.shared);
|
|
49
|
+
let code;
|
|
47
50
|
if (true === options.runModule) {
|
|
48
51
|
const finalPreModules = [
|
|
49
52
|
getEarlyShared(syncSharedModules),
|
|
50
53
|
getEarlyRemotes(syncRemoteModules),
|
|
51
54
|
...preModules
|
|
52
55
|
];
|
|
53
|
-
|
|
56
|
+
code = getBundleCode(entryPoint, finalPreModules, graph, options);
|
|
57
|
+
} else if (isProjectSource(entryPoint, options.projectRoot)) {
|
|
58
|
+
const bundlePath = getBundlePath(entryPoint, options.projectRoot, mfConfig.exposes, isUsingMFBundleCommand);
|
|
59
|
+
const finalPreModules = [
|
|
60
|
+
getSyncShared(syncSharedModules, bundlePath, mfConfig.name),
|
|
61
|
+
getSyncRemotes(syncRemoteModules, bundlePath, mfConfig.name)
|
|
62
|
+
];
|
|
63
|
+
if (false === options.modulesOnly) finalPreModules.push(...preModules);
|
|
64
|
+
const finalOptions = {
|
|
65
|
+
...options,
|
|
66
|
+
modulesOnly: false
|
|
67
|
+
};
|
|
68
|
+
code = getBundleCode(entryPoint, finalPreModules, graph, finalOptions);
|
|
69
|
+
} else code = getBundleCode(entryPoint, preModules, graph, options);
|
|
70
|
+
if (manifestPath) {
|
|
71
|
+
(0, external_manifest_js_namespaceObject.recordBundleHash)(bundleHashes, code, entryPoint, options.projectRoot, mfConfig);
|
|
72
|
+
(0, external_manifest_js_namespaceObject.updateManifest)(manifestPath, mfConfig, bundleHashes, manifestOptions);
|
|
54
73
|
}
|
|
55
|
-
|
|
56
|
-
const bundlePath = getBundlePath(entryPoint, options.projectRoot, mfConfig.exposes, isUsingMFBundleCommand);
|
|
57
|
-
const finalPreModules = [
|
|
58
|
-
getSyncShared(syncSharedModules, bundlePath, mfConfig.name),
|
|
59
|
-
getSyncRemotes(syncRemoteModules, bundlePath, mfConfig.name)
|
|
60
|
-
];
|
|
61
|
-
if (false === options.modulesOnly) finalPreModules.push(...preModules);
|
|
62
|
-
const finalOptions = {
|
|
63
|
-
...options,
|
|
64
|
-
modulesOnly: false
|
|
65
|
-
};
|
|
66
|
-
return getBundleCode(entryPoint, finalPreModules, graph, finalOptions);
|
|
74
|
+
return code;
|
|
67
75
|
};
|
|
68
76
|
}
|
|
69
77
|
function collectSyncRemoteModules(graph, _remotes) {
|
|
@@ -3,31 +3,39 @@ import 'module';
|
|
|
3
3
|
import node_path from "node:path";
|
|
4
4
|
import { ConfigError } from "../utils/errors.mjs";
|
|
5
5
|
import { toPosixPath } from "./helpers.mjs";
|
|
6
|
+
import { recordBundleHash, updateManifest } from "./manifest.mjs";
|
|
6
7
|
import { CountingSet, baseJSBundle, bundleToString } from "../utils/metro-compat.mjs";
|
|
7
|
-
function getModuleFederationSerializer(mfConfig, isUsingMFBundleCommand) {
|
|
8
|
+
function getModuleFederationSerializer(mfConfig, isUsingMFBundleCommand, manifestPath, manifestOptions) {
|
|
9
|
+
const bundleHashes = new Map();
|
|
8
10
|
return async (entryPoint, preModules, graph, options)=>{
|
|
9
11
|
const syncRemoteModules = collectSyncRemoteModules(graph, mfConfig.remotes);
|
|
10
12
|
const syncSharedModules = collectSyncSharedModules(graph, mfConfig.shared);
|
|
13
|
+
let code;
|
|
11
14
|
if (true === options.runModule) {
|
|
12
15
|
const finalPreModules = [
|
|
13
16
|
getEarlyShared(syncSharedModules),
|
|
14
17
|
getEarlyRemotes(syncRemoteModules),
|
|
15
18
|
...preModules
|
|
16
19
|
];
|
|
17
|
-
|
|
20
|
+
code = getBundleCode(entryPoint, finalPreModules, graph, options);
|
|
21
|
+
} else if (isProjectSource(entryPoint, options.projectRoot)) {
|
|
22
|
+
const bundlePath = getBundlePath(entryPoint, options.projectRoot, mfConfig.exposes, isUsingMFBundleCommand);
|
|
23
|
+
const finalPreModules = [
|
|
24
|
+
getSyncShared(syncSharedModules, bundlePath, mfConfig.name),
|
|
25
|
+
getSyncRemotes(syncRemoteModules, bundlePath, mfConfig.name)
|
|
26
|
+
];
|
|
27
|
+
if (false === options.modulesOnly) finalPreModules.push(...preModules);
|
|
28
|
+
const finalOptions = {
|
|
29
|
+
...options,
|
|
30
|
+
modulesOnly: false
|
|
31
|
+
};
|
|
32
|
+
code = getBundleCode(entryPoint, finalPreModules, graph, finalOptions);
|
|
33
|
+
} else code = getBundleCode(entryPoint, preModules, graph, options);
|
|
34
|
+
if (manifestPath) {
|
|
35
|
+
recordBundleHash(bundleHashes, code, entryPoint, options.projectRoot, mfConfig);
|
|
36
|
+
updateManifest(manifestPath, mfConfig, bundleHashes, manifestOptions);
|
|
18
37
|
}
|
|
19
|
-
|
|
20
|
-
const bundlePath = getBundlePath(entryPoint, options.projectRoot, mfConfig.exposes, isUsingMFBundleCommand);
|
|
21
|
-
const finalPreModules = [
|
|
22
|
-
getSyncShared(syncSharedModules, bundlePath, mfConfig.name),
|
|
23
|
-
getSyncRemotes(syncRemoteModules, bundlePath, mfConfig.name)
|
|
24
|
-
];
|
|
25
|
-
if (false === options.modulesOnly) finalPreModules.push(...preModules);
|
|
26
|
-
const finalOptions = {
|
|
27
|
-
...options,
|
|
28
|
-
modulesOnly: false
|
|
29
|
-
};
|
|
30
|
-
return getBundleCode(entryPoint, finalPreModules, graph, finalOptions);
|
|
38
|
+
return code;
|
|
31
39
|
};
|
|
32
40
|
}
|
|
33
41
|
function collectSyncRemoteModules(graph, _remotes) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@module-federation/metro",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "Module Federation for Metro bundler",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"module-federation",
|
|
@@ -57,9 +57,9 @@
|
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"@expo/metro-runtime": "^5.0.4",
|
|
60
|
-
"@module-federation/dts-plugin": "2.
|
|
61
|
-
"@module-federation/runtime": "2.
|
|
62
|
-
"@module-federation/sdk": "2.
|
|
60
|
+
"@module-federation/dts-plugin": "2.5.0",
|
|
61
|
+
"@module-federation/runtime": "2.5.0",
|
|
62
|
+
"@module-federation/sdk": "2.5.0"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"@babel/types": "^7.25.0",
|