@module-federation/data-prefetch 0.0.0-next-20240701101956 → 0.0.0-next-20240808065005

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/CHANGELOG.md CHANGED
@@ -1,11 +1,9 @@
1
1
  @module-federation/data-prefetch
2
2
 
3
- ## 0.0.0-next-20240701101956
3
+ ## 0.0.0-next-20240808065005
4
4
 
5
5
  ### Patch Changes
6
6
 
7
7
  - 3ddab21: feat(@module-federation/data-prefetch): support data prefetch in Module Federation
8
- - Updated dependencies [09b792d]
9
- - Updated dependencies [09b792d]
10
- - @module-federation/sdk@0.0.0-next-20240701101956
11
- - @module-federation/runtime@0.0.0-next-20240701101956
8
+ - @module-federation/runtime@0.0.0-next-20240808065005
9
+ - @module-federation/sdk@0.0.0-next-20240808065005
@@ -1,11 +1,19 @@
1
1
  // Import the necessary modules and functions
2
2
  import { MFDataPrefetch } from '../src/prefetch';
3
- import { loadScript } from '@module-federation/sdk';
3
+ import {
4
+ loadScript,
5
+ MFPrefetchCommon,
6
+ encodeName,
7
+ } from '@module-federation/sdk';
4
8
 
5
9
  // Mock loadScript function from SDK
6
- jest.mock('@module-federation/sdk', () => ({
7
- loadScript: jest.fn(() => Promise.resolve()),
8
- }));
10
+ jest.mock('@module-federation/sdk', () => {
11
+ const originalModule = jest.requireActual('@module-federation/sdk');
12
+ return {
13
+ ...originalModule,
14
+ loadScript: jest.fn(() => Promise.resolve()),
15
+ };
16
+ });
9
17
 
10
18
  describe('MF Data Prefetch', () => {
11
19
  let prefetch: MFDataPrefetch;
@@ -17,6 +25,7 @@ describe('MF Data Prefetch', () => {
17
25
  globalName: 'TestGlobalName',
18
26
  },
19
27
  };
28
+ const exposeId = `${options.name}/button/${MFPrefetchCommon.identifier}`;
20
29
 
21
30
  beforeEach(() => {
22
31
  globalThis.__FEDERATION__.__PREFETCH__ = {
@@ -53,20 +62,22 @@ describe('MF Data Prefetch', () => {
53
62
  nyPrefetch: () => {},
54
63
  };
55
64
  const projectExport = {
56
- [options.name]: exposeExport,
65
+ [encodeName(exposeId)]: exposeExport,
57
66
  };
58
67
  globalThis.__FEDERATION__.__PREFETCH__.__PREFETCH_EXPORTS__[options.name] =
59
68
  Promise.resolve(projectExport);
60
69
 
61
70
  await prefetch.getProjectExports();
62
- expect(prefetch.getExposeExports(options.name)).toEqual(exposeExport);
71
+ expect(prefetch.getExposeExports(`${options.name}/button`)).toEqual(
72
+ exposeExport,
73
+ );
63
74
  });
64
75
  // Prefetching with memory and executing prefetch function
65
76
  it('executes prefetch using prefetch function with and without memory', async () => {
66
77
  const id = options.name;
67
78
  const functionId = 'nyPrefetch';
68
79
  const refetchParams = 'testParams';
69
- const prefetchOptions = { id, functionId, refetchParams };
80
+ const prefetchOptions = { id: `${id}/button`, functionId, refetchParams };
70
81
 
71
82
  // Creating a mock prefetch function
72
83
  const executePrefetch = jest.fn(() => 'Expected Result');
@@ -75,7 +86,7 @@ describe('MF Data Prefetch', () => {
75
86
  // Mock Project Exports
76
87
  globalThis.__FEDERATION__.__PREFETCH__.__PREFETCH_EXPORTS__[id] =
77
88
  Promise.resolve({
78
- [id]: prefetchExports,
89
+ [encodeName(exposeId)]: prefetchExports,
79
90
  });
80
91
 
81
92
  await prefetch.getProjectExports();
@@ -57,8 +57,9 @@ describe('usePrefetch', () => {
57
57
  const exposeExport = {
58
58
  [functionId]: executePrefetch,
59
59
  };
60
+ const exposeId = `${options.name}/button/${ModuleFederationSDK.MFPrefetchCommon.identifier}`;
60
61
  const projectExport = {
61
- [options.name]: exposeExport,
62
+ [ModuleFederationSDK.encodeName(exposeId)]: exposeExport,
62
63
  };
63
64
  globalThis.__FEDERATION__.__PREFETCH__.__PREFETCH_EXPORTS__[options.name] =
64
65
  Promise.resolve(projectExport);
@@ -76,7 +77,7 @@ describe('usePrefetch', () => {
76
77
 
77
78
  it('should prefetch data on first mount', async () => {
78
79
  const { result } = renderHook(() =>
79
- usePrefetch({ id: options.name, functionId }),
80
+ usePrefetch({ id: `${options.name}/button`, functionId }),
80
81
  );
81
82
  await result.current[0];
82
83
  expect(executePrefetch).toHaveBeenCalled();
@@ -86,14 +87,14 @@ describe('usePrefetch', () => {
86
87
 
87
88
  it('should refetch data when refreshExecutor is called', async () => {
88
89
  const { result } = renderHook(() =>
89
- usePrefetch({ id: options.name, functionId }),
90
+ usePrefetch({ id: `${options.name}/button`, functionId }),
90
91
  );
91
92
 
92
93
  await result.current[0];
93
94
  expect(executePrefetch).toHaveBeenCalled();
94
95
  executePrefetch.mockClear();
95
96
  const { result: newCallResult } = renderHook(() =>
96
- usePrefetch({ id: options.name, functionId }),
97
+ usePrefetch({ id: `${options.name}/button`, functionId }),
97
98
  );
98
99
  await newCallResult.current[0];
99
100
  expect(executePrefetch).not.toHaveBeenCalled();
@@ -4,7 +4,7 @@ interface BabelPluginOptions {
4
4
  hook_id: string;
5
5
  import_pkg: string;
6
6
  attribute: string;
7
- mf_name: string;
7
+ name: string;
8
8
  exposes: moduleFederationPlugin.ModuleFederationPluginOptions['exposes'];
9
9
  }
10
10
  declare const _default: (babel: {
package/dist/cli/babel.js CHANGED
@@ -37,7 +37,7 @@ var babel_default = (babel, options) => {
37
37
  const t = babel.types;
38
38
  let shouldHandle = false;
39
39
  let scope = "";
40
- const { mf_name: name, exposes } = options;
40
+ const { name, exposes } = options;
41
41
  if (!exposes) {
42
42
  return {};
43
43
  }
package/dist/cli/index.js CHANGED
@@ -88,6 +88,14 @@ var PrefetchPlugin = class {
88
88
  this.options.runtimePlugins.push(
89
89
  import_path2.default.resolve(__dirname, "../esm/shared/index.js")
90
90
  );
91
+ const encodedName = (0, import_sdk2.encodeName)(name);
92
+ const asyncEntryPath = import_path2.default.resolve(
93
+ compiler.options.context,
94
+ `node_modules/${TEMP_DIR}/${encodedName}/bootstrap.js`
95
+ );
96
+ if (import_fs_extra2.default.existsSync(asyncEntryPath)) {
97
+ import_fs_extra2.default.unlinkSync(asyncEntryPath);
98
+ }
91
99
  if (!this.options.dataPrefetch) {
92
100
  return;
93
101
  }
@@ -118,11 +126,6 @@ var PrefetchPlugin = class {
118
126
  if (!this._reWriteExports) {
119
127
  return;
120
128
  }
121
- const encodedName = (0, import_sdk2.encodeName)(name);
122
- const asyncEntryPath = import_path2.default.resolve(
123
- compiler.options.context,
124
- `node_modules/${TEMP_DIR}/${encodedName}/bootstrap.js`
125
- );
126
129
  const tempDirRealPath = import_path2.default.resolve(
127
130
  compiler.options.context,
128
131
  "node_modules",
@@ -9,6 +9,7 @@ import {
9
9
  } from "./chunk-EWCGK4XA.js";
10
10
 
11
11
  // src/plugin.ts
12
+ import { Module } from "@module-federation/runtime";
12
13
  import { getResourceUrl } from "@module-federation/sdk";
13
14
  var loadingArray = [];
14
15
  var strategy = "loaded-first";
@@ -111,6 +112,21 @@ var prefetchPlugin = () => ({
111
112
  return options;
112
113
  }
113
114
  const promise = instance.loadEntry(prefetchUrl).then(async () => {
115
+ let module = origin.moduleCache.get(remote.name);
116
+ const moduleOptions = {
117
+ host: origin,
118
+ remoteInfo: remote
119
+ };
120
+ if (!module) {
121
+ module = new Module(moduleOptions);
122
+ origin.moduleCache.set(remote.name, module);
123
+ }
124
+ const idPart = id.split("/");
125
+ let expose = idPart[idPart.length - 1];
126
+ if (expose !== ".") {
127
+ expose = `./${expose}`;
128
+ }
129
+ await module.get(id, expose, {}, remoteSnapshot);
114
130
  const projectExports = instance.getProjectExports();
115
131
  if (projectExports instanceof Promise) {
116
132
  await projectExports;
@@ -7,7 +7,7 @@ var babel_default = (babel, options) => {
7
7
  const t = babel.types;
8
8
  let shouldHandle = false;
9
9
  let scope = "";
10
- const { mf_name: name, exposes } = options;
10
+ const { name, exposes } = options;
11
11
  if (!exposes) {
12
12
  return {};
13
13
  }
@@ -60,6 +60,14 @@ var PrefetchPlugin = class {
60
60
  this.options.runtimePlugins.push(
61
61
  path2.resolve(__dirname, "../esm/shared/index.js")
62
62
  );
63
+ const encodedName = encodeName(name);
64
+ const asyncEntryPath = path2.resolve(
65
+ compiler.options.context,
66
+ `node_modules/${TEMP_DIR}/${encodedName}/bootstrap.js`
67
+ );
68
+ if (fs2.existsSync(asyncEntryPath)) {
69
+ fs2.unlinkSync(asyncEntryPath);
70
+ }
63
71
  if (!this.options.dataPrefetch) {
64
72
  return;
65
73
  }
@@ -90,11 +98,6 @@ var PrefetchPlugin = class {
90
98
  if (!this._reWriteExports) {
91
99
  return;
92
100
  }
93
- const encodedName = encodeName(name);
94
- const asyncEntryPath = path2.resolve(
95
- compiler.options.context,
96
- `node_modules/${TEMP_DIR}/${encodedName}/bootstrap.js`
97
- );
98
101
  const tempDirRealPath = path2.resolve(
99
102
  compiler.options.context,
100
103
  "node_modules",
package/dist/esm/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  prefetchPlugin
3
- } from "./chunk-VJO2H3UO.js";
3
+ } from "./chunk-WLE6YNDH.js";
4
4
  import "./chunk-TTJJJ2WZ.js";
5
5
  import {
6
6
  MFDataPrefetch
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  plugin_default,
3
3
  prefetchPlugin
4
- } from "./chunk-VJO2H3UO.js";
4
+ } from "./chunk-WLE6YNDH.js";
5
5
  import "./chunk-TTJJJ2WZ.js";
6
6
  import "./chunk-JEPJP5O3.js";
7
7
  import "./chunk-EWCGK4XA.js";
package/dist/index.js CHANGED
@@ -192,6 +192,7 @@ var MFDataPrefetch = class {
192
192
  };
193
193
 
194
194
  // src/plugin.ts
195
+ var import_runtime2 = require("@module-federation/runtime");
195
196
  var import_sdk4 = require("@module-federation/sdk");
196
197
 
197
198
  // src/logger/index.ts
@@ -300,6 +301,21 @@ var prefetchPlugin = () => ({
300
301
  return options;
301
302
  }
302
303
  const promise = instance.loadEntry(prefetchUrl).then(async () => {
304
+ let module2 = origin.moduleCache.get(remote.name);
305
+ const moduleOptions = {
306
+ host: origin,
307
+ remoteInfo: remote
308
+ };
309
+ if (!module2) {
310
+ module2 = new import_runtime2.Module(moduleOptions);
311
+ origin.moduleCache.set(remote.name, module2);
312
+ }
313
+ const idPart = id.split("/");
314
+ let expose = idPart[idPart.length - 1];
315
+ if (expose !== ".") {
316
+ expose = `./${expose}`;
317
+ }
318
+ await module2.get(id, expose, {}, remoteSnapshot);
303
319
  const projectExports = instance.getProjectExports();
304
320
  if (projectExports instanceof Promise) {
305
321
  await projectExports;
package/dist/plugin.js CHANGED
@@ -24,6 +24,7 @@ __export(plugin_exports, {
24
24
  prefetchPlugin: () => prefetchPlugin
25
25
  });
26
26
  module.exports = __toCommonJS(plugin_exports);
27
+ var import_runtime2 = require("@module-federation/runtime");
27
28
  var import_sdk4 = require("@module-federation/sdk");
28
29
 
29
30
  // src/common/runtime-utils.ts
@@ -296,6 +297,21 @@ var prefetchPlugin = () => ({
296
297
  return options;
297
298
  }
298
299
  const promise = instance.loadEntry(prefetchUrl).then(async () => {
300
+ let module2 = origin.moduleCache.get(remote.name);
301
+ const moduleOptions = {
302
+ host: origin,
303
+ remoteInfo: remote
304
+ };
305
+ if (!module2) {
306
+ module2 = new import_runtime2.Module(moduleOptions);
307
+ origin.moduleCache.set(remote.name, module2);
308
+ }
309
+ const idPart = id.split("/");
310
+ let expose = idPart[idPart.length - 1];
311
+ if (expose !== ".") {
312
+ expose = `./${expose}`;
313
+ }
314
+ await module2.get(id, expose, {}, remoteSnapshot);
299
315
  const projectExports = instance.getProjectExports();
300
316
  if (projectExports instanceof Promise) {
301
317
  await projectExports;
package/jest.config.js CHANGED
@@ -21,7 +21,7 @@ module.exports = {
21
21
  '/node_modules/(?!((@byted/garfish-)|(byted-tea-sdk))).+\\.js$',
22
22
  ],
23
23
  transform: {
24
- '^.+\\.(t|j)sx?$': ['@swc/jest'],
24
+ '^.+\\.(t|j)sx?$': ['@swc/jest', { swcrc: false }],
25
25
  },
26
26
  rootDir: __dirname,
27
27
  testMatch: ['<rootDir>__tests__/**/**.spec.[jt]s?(x)'],
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@module-federation/data-prefetch",
3
3
  "description": "Module Federation Data Prefetch",
4
- "version": "0.0.0-next-20240701101956",
4
+ "version": "0.0.0-next-20240808065005",
5
5
  "author": "nieyan <nyqykk@foxmail.com>",
6
6
  "homepage": "https://github.com/module-federation/core",
7
7
  "license": "MIT",
@@ -85,8 +85,8 @@
85
85
  },
86
86
  "dependencies": {
87
87
  "fs-extra": "9.1.0",
88
- "@module-federation/sdk": "0.0.0-next-20240701101956",
89
- "@module-federation/runtime": "0.0.0-next-20240701101956"
88
+ "@module-federation/sdk": "0.0.0-next-20240808065005",
89
+ "@module-federation/runtime": "0.0.0-next-20240808065005"
90
90
  },
91
91
  "scripts": {
92
92
  "dev": "cross-env WATCH=true tsup",
package/src/cli/babel.ts CHANGED
@@ -9,7 +9,7 @@ interface BabelPluginOptions {
9
9
  hook_id: string;
10
10
  import_pkg: string;
11
11
  attribute: string;
12
- mf_name: string;
12
+ name: string;
13
13
  exposes: moduleFederationPlugin.ModuleFederationPluginOptions['exposes'];
14
14
  }
15
15
 
@@ -18,7 +18,7 @@ export default (babel: { types: any }, options: BabelPluginOptions) => {
18
18
  const t = babel.types;
19
19
  let shouldHandle = false;
20
20
  let scope = '';
21
- const { mf_name: name, exposes } = options;
21
+ const { name, exposes } = options;
22
22
  if (!exposes) {
23
23
  return {};
24
24
  }
package/src/cli/index.ts CHANGED
@@ -41,6 +41,14 @@ export class PrefetchPlugin implements WebpackPluginInstance {
41
41
  this.options.runtimePlugins!.push(
42
42
  path.resolve(__dirname, '../esm/shared/index.js'),
43
43
  );
44
+ const encodedName = encodeName(name as string);
45
+ const asyncEntryPath = path.resolve(
46
+ compiler.options.context,
47
+ `node_modules/${TEMP_DIR}/${encodedName}/bootstrap.js`,
48
+ );
49
+ if (fs.existsSync(asyncEntryPath)) {
50
+ fs.unlinkSync(asyncEntryPath);
51
+ }
44
52
  if (!this.options.dataPrefetch) {
45
53
  return;
46
54
  }
@@ -73,12 +81,6 @@ export class PrefetchPlugin implements WebpackPluginInstance {
73
81
  if (!this._reWriteExports) {
74
82
  return;
75
83
  }
76
-
77
- const encodedName = encodeName(name as string);
78
- const asyncEntryPath = path.resolve(
79
- compiler.options.context,
80
- `node_modules/${TEMP_DIR}/${encodedName}/bootstrap.js`,
81
- );
82
84
  const tempDirRealPath = path.resolve(
83
85
  compiler.options.context,
84
86
  'node_modules',
package/src/plugin.ts CHANGED
@@ -1,4 +1,8 @@
1
- import type { FederationRuntimePlugin } from '@module-federation/runtime/types';
1
+ import { Module } from '@module-federation/runtime';
2
+ import type {
3
+ FederationRuntimePlugin,
4
+ RemoteInfo,
5
+ } from '@module-federation/runtime/types';
2
6
  import { ModuleInfo, getResourceUrl } from '@module-federation/sdk';
3
7
 
4
8
  import { getSignalFromManifest } from './common/runtime-utils';
@@ -150,6 +154,22 @@ export const prefetchPlugin = (): FederationRuntimePlugin => ({
150
154
  }
151
155
 
152
156
  const promise = instance.loadEntry(prefetchUrl).then(async () => {
157
+ let module = origin.moduleCache.get(remote.name);
158
+ const moduleOptions = {
159
+ host: origin,
160
+ remoteInfo: remote as RemoteInfo,
161
+ };
162
+ if (!module) {
163
+ module = new Module(moduleOptions);
164
+ origin.moduleCache.set(remote.name, module);
165
+ }
166
+ const idPart = id.split('/');
167
+ let expose = idPart[idPart.length - 1];
168
+ if (expose !== '.') {
169
+ expose = `./${expose}`;
170
+ }
171
+ await module.get(id, expose, {}, remoteSnapshot);
172
+
153
173
  const projectExports = instance!.getProjectExports();
154
174
  if (projectExports instanceof Promise) {
155
175
  await projectExports;
package/src/prefetch.ts CHANGED
@@ -106,7 +106,8 @@ export class MFDataPrefetch {
106
106
  globalThis.__FEDERATION__.__PREFETCH__.__PREFETCH_EXPORTS__?.[name];
107
107
  const resolve = exportsPromise.then(
108
108
  (exports: Record<string, Record<string, any>> = {}) => {
109
- // 根据函数名后缀匹配 prefetch,以便后续拓展其他能力,不应直接将所有函数都识别为 prefetch 函数
109
+ // Match prefetch based on the function name suffix so that other capabilities can be expanded later.
110
+ // Not all functions should be directly identified as prefetch functions
110
111
  const memory: Record<string, Record<string, any>> = {};
111
112
  Object.keys(exports).forEach((key) => {
112
113
  memory[key] = {};