@module-federation/data-prefetch 0.0.0-next-20240617071542 → 0.0.0-next-20240702090143

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,10 +1,11 @@
1
1
  @module-federation/data-prefetch
2
2
 
3
- ## 0.0.0-next-20240617071542
3
+ ## 0.0.0-next-20240702090143
4
4
 
5
5
  ### Patch Changes
6
6
 
7
- - Updated dependencies [103cd07]
8
- - Updated dependencies [364f2bc]
9
- - @module-federation/runtime@0.0.0-next-20240617071542
10
- - @module-federation/sdk@0.0.0-next-20240617071542
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-20240702090143
11
+ - @module-federation/runtime@0.0.0-next-20240702090143
package/README.md CHANGED
@@ -1,2 +1 @@
1
- Vmok Interface Prefetch
2
- https://vmok.bytedance.net/guide/performance/prefetch.html
1
+ Module Federation Data Prefetch
@@ -0,0 +1,75 @@
1
+ /// <reference types="jest" />
2
+
3
+ import path from 'path';
4
+ import fs from 'fs';
5
+ import { BabelFileResult, transformFileSync } from '@babel/core';
6
+ // @ts-ignore no use
7
+ import type from '@types/jest';
8
+
9
+ import babelPlugin from '../src/cli/babel';
10
+
11
+ const emptyRegexp = /\s+/g;
12
+ describe('Babel Plugin Test', () => {
13
+ const options = {
14
+ name: '@mf/test',
15
+ exposes: { './expose': path.resolve(__dirname, 'test') },
16
+ };
17
+
18
+ const testFilePath = path.join(__dirname, './test');
19
+
20
+ beforeEach(() => {
21
+ fs.mkdirSync(path.dirname(testFilePath), { recursive: true });
22
+ fs.closeSync(fs.openSync(testFilePath, 'w'));
23
+ });
24
+
25
+ afterEach(() => {
26
+ fs.unlinkSync(testFilePath);
27
+ });
28
+
29
+ // Check if the plugin will add the id parameter when it is not present
30
+ test('it adds id argument to usePrefetch call when it is absent', () => {
31
+ const input = `
32
+ import { usePrefetch } from "@module-federation/data-prefetch/react";
33
+ usePrefetch({});
34
+ `;
35
+
36
+ const expected = `
37
+ import { usePrefetch } from "@module-federation/data-prefetch/react";
38
+ usePrefetch({ id: "@mf/test/expose" });
39
+ `;
40
+
41
+ fs.writeFileSync(testFilePath, input);
42
+ const { code } = transformFileSync(testFilePath, {
43
+ plugins: [[babelPlugin, options]],
44
+ configFile: false,
45
+ }) as BabelFileResult;
46
+
47
+ expect(code?.replace(emptyRegexp, '')).toBe(
48
+ expected.replace(emptyRegexp, ''),
49
+ );
50
+ });
51
+
52
+ // The plugin should retain the existing id parameter in the usePrefetch call
53
+ test('it does not overwrite existing id argument in usePrefetch call', () => {
54
+ const input = `
55
+ import { usePrefetch } from "@module-federation/data-prefetch/react";
56
+ usePrefetch({ id: "existingId" });
57
+ `;
58
+
59
+ const expected = `
60
+ import { usePrefetch } from "@module-federation/data-prefetch/react";
61
+ usePrefetch({ id: "existingId" });
62
+ `;
63
+
64
+ fs.writeFileSync(testFilePath, input);
65
+ const { code } = transformFileSync(testFilePath, {
66
+ plugins: [[babelPlugin, options]],
67
+ configFile: false,
68
+ babelrc: false,
69
+ }) as BabelFileResult;
70
+
71
+ expect(code?.replace(emptyRegexp, '')).toBe(
72
+ expected.replace(emptyRegexp, ''),
73
+ );
74
+ });
75
+ });
@@ -0,0 +1,127 @@
1
+ // Import the necessary modules and functions
2
+ import { MFDataPrefetch } from '../src/prefetch';
3
+ import { loadScript } from '@module-federation/sdk';
4
+
5
+ // Mock loadScript function from SDK
6
+ jest.mock('@module-federation/sdk', () => ({
7
+ loadScript: jest.fn(() => Promise.resolve()),
8
+ }));
9
+
10
+ describe('MF Data Prefetch', () => {
11
+ let prefetch: MFDataPrefetch;
12
+
13
+ const options = {
14
+ name: '@mf/test',
15
+ remoteSnapshot: {
16
+ buildVersion: '1.0.0',
17
+ globalName: 'TestGlobalName',
18
+ },
19
+ };
20
+
21
+ beforeEach(() => {
22
+ globalThis.__FEDERATION__.__PREFETCH__ = {
23
+ entryLoading: {},
24
+ instance: new Map(),
25
+ __PREFETCH_EXPORTS__: {},
26
+ };
27
+ // @ts-ignore
28
+ prefetch = new MFDataPrefetch(options);
29
+ });
30
+ afterAll(() => {
31
+ // @ts-ignore
32
+ delete globalThis.__FEDERATION__;
33
+ });
34
+
35
+ // Instance gets added to global memory on creation
36
+ it('adds itself to global instances on creation', () => {
37
+ expect(prefetch.global.instance.get(options.name)).toBe(prefetch);
38
+ });
39
+
40
+ // Loads entry script using loadScript from sdk
41
+ it('loads entry script using loadScript from sdk', async () => {
42
+ const url = 'testUrl'; // Url of the script to be loaded
43
+
44
+ await prefetch.loadEntry(url); // Call `loadEntry` function
45
+
46
+ // Expect that the loadScript function is called with the correct url
47
+ expect(loadScript).toHaveBeenCalledWith(url, expect.any(Object));
48
+ });
49
+
50
+ // Retrieves project exports
51
+ it('gets project exports', async () => {
52
+ const exposeExport = {
53
+ nyPrefetch: () => {},
54
+ };
55
+ const projectExport = {
56
+ [options.name]: exposeExport,
57
+ };
58
+ globalThis.__FEDERATION__.__PREFETCH__.__PREFETCH_EXPORTS__[options.name] =
59
+ Promise.resolve(projectExport);
60
+
61
+ await prefetch.getProjectExports();
62
+ expect(prefetch.getExposeExports(options.name)).toEqual(exposeExport);
63
+ });
64
+ // Prefetching with memory and executing prefetch function
65
+ it('executes prefetch using prefetch function with and without memory', async () => {
66
+ const id = options.name;
67
+ const functionId = 'nyPrefetch';
68
+ const refetchParams = 'testParams';
69
+ const prefetchOptions = { id, functionId, refetchParams };
70
+
71
+ // Creating a mock prefetch function
72
+ const executePrefetch = jest.fn(() => 'Expected Result');
73
+ const prefetchExports = { [functionId]: executePrefetch };
74
+
75
+ // Mock Project Exports
76
+ globalThis.__FEDERATION__.__PREFETCH__.__PREFETCH_EXPORTS__[id] =
77
+ Promise.resolve({
78
+ [id]: prefetchExports,
79
+ });
80
+
81
+ await prefetch.getProjectExports();
82
+ // Call the prefetch function first time
83
+ let result = await prefetch.prefetch(prefetchOptions);
84
+
85
+ // Verify that executePrefetch function is correctly executed
86
+ expect(executePrefetch).toHaveBeenCalled();
87
+
88
+ // Clear mock function calls data
89
+ executePrefetch.mockClear();
90
+
91
+ // Call the prefetch function again
92
+ result = await prefetch.prefetch(prefetchOptions);
93
+
94
+ // Verify that executePrefetch function is NOT called this time (since the result should come from memory)
95
+ expect(executePrefetch).not.toHaveBeenCalled();
96
+
97
+ // Clear mock function calls data
98
+ executePrefetch.mockClear();
99
+
100
+ prefetch.markOutdate(prefetchOptions, true);
101
+
102
+ // Call the prefetch function first time
103
+ result = await prefetch.prefetch(prefetchOptions);
104
+
105
+ // Verify that executePrefetch function is correctly executed
106
+ expect(executePrefetch).toHaveBeenCalled();
107
+ });
108
+
109
+ // Checking outdate marking
110
+ it('checks outdate marking', () => {
111
+ const markOptions = { id: 'testId', functionId: 'testFunction' };
112
+
113
+ // Mark the function as outdated
114
+ prefetch.markOutdate(markOptions, true);
115
+
116
+ // Verify that the function is marked as outdated
117
+ let isOutdated = prefetch.checkOutdate(markOptions);
118
+ expect(isOutdated).toBe(true);
119
+
120
+ // Mark the function as up-to-date
121
+ prefetch.markOutdate(markOptions, false);
122
+
123
+ // Verify that the function is marked as up-to-date
124
+ isOutdated = prefetch.checkOutdate(markOptions);
125
+ expect(isOutdated).toBe(false);
126
+ });
127
+ });
@@ -0,0 +1,109 @@
1
+ import { renderHook, act } from '@testing-library/react-hooks';
2
+ import * as ModuleFederationSDK from '@module-federation/sdk';
3
+ import { usePrefetch } from '../src/react';
4
+ import { MFDataPrefetch } from '../src/prefetch';
5
+
6
+ const mockLoadScript = jest.spyOn(ModuleFederationSDK, 'loadScript');
7
+ mockLoadScript.mockImplementation(() => Promise.resolve());
8
+
9
+ describe('usePrefetch', () => {
10
+ // Mock prefetch function
11
+ global.fetch = jest.fn(() =>
12
+ Promise.resolve({
13
+ ok: true,
14
+ status: 200,
15
+ statusText: 'OK',
16
+ redirected: false,
17
+ type: 'basic',
18
+ url: '',
19
+ clone: jest.fn(),
20
+ headers: new Headers(),
21
+ body: null,
22
+ bodyUsed: false,
23
+ text: () => Promise.resolve(JSON.stringify({ data: 'testData' })),
24
+ json: () => Promise.resolve({ data: 'testData' }),
25
+ formData: () => Promise.resolve(new FormData()),
26
+ arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)),
27
+ blob: () => Promise.resolve(new Blob()),
28
+ }),
29
+ );
30
+
31
+ let prefetch: MFDataPrefetch;
32
+
33
+ const options = {
34
+ // Options that will be passed to the `MFDataPrefetch` constructor
35
+ name: '@mf/test',
36
+ remoteSnapshot: {
37
+ buildVersion: '1.0.0',
38
+ globalName: 'TestGlobalName',
39
+ },
40
+ };
41
+ const testData = 'testData';
42
+ const newTestData = 'newTestData';
43
+ const functionId = 'testPrefetch';
44
+ const executePrefetch = jest.fn((params: string) =>
45
+ Promise.resolve(params ? params : testData),
46
+ );
47
+
48
+ beforeEach(() => {
49
+ globalThis.__FEDERATION__.__PREFETCH__ = {
50
+ entryLoading: {},
51
+ instance: new Map(),
52
+ __PREFETCH_EXPORTS__: {},
53
+ };
54
+ // @ts-ignore
55
+ prefetch = new MFDataPrefetch(options); // Create a new instance of `MFDataPrefetch` class before each test
56
+
57
+ const exposeExport = {
58
+ [functionId]: executePrefetch,
59
+ };
60
+ const projectExport = {
61
+ [options.name]: exposeExport,
62
+ };
63
+ globalThis.__FEDERATION__.__PREFETCH__.__PREFETCH_EXPORTS__[options.name] =
64
+ Promise.resolve(projectExport);
65
+ });
66
+
67
+ afterEach(() => {
68
+ executePrefetch.mockClear();
69
+ mockLoadScript.mockRestore();
70
+ });
71
+
72
+ afterAll(() => {
73
+ // @ts-ignore
74
+ delete globalThis.__FEDERATION__;
75
+ });
76
+
77
+ it('should prefetch data on first mount', async () => {
78
+ const { result } = renderHook(() =>
79
+ usePrefetch({ id: options.name, functionId }),
80
+ );
81
+ await result.current[0];
82
+ expect(executePrefetch).toHaveBeenCalled();
83
+ // Verify the prefechState
84
+ expect(result.current[0]).resolves.toEqual(testData);
85
+ });
86
+
87
+ it('should refetch data when refreshExecutor is called', async () => {
88
+ const { result } = renderHook(() =>
89
+ usePrefetch({ id: options.name, functionId }),
90
+ );
91
+
92
+ await result.current[0];
93
+ expect(executePrefetch).toHaveBeenCalled();
94
+ executePrefetch.mockClear();
95
+ const { result: newCallResult } = renderHook(() =>
96
+ usePrefetch({ id: options.name, functionId }),
97
+ );
98
+ await newCallResult.current[0];
99
+ expect(executePrefetch).not.toHaveBeenCalled();
100
+ // Call refreshExecutor
101
+ act(() => {
102
+ result.current[1](newTestData);
103
+ });
104
+
105
+ expect(executePrefetch).toHaveBeenCalled();
106
+ // // Verify the prefetchState after refetch
107
+ expect(result.current[0]).resolves.toEqual(newTestData);
108
+ });
109
+ });
package/dist/cli/index.js CHANGED
@@ -65,28 +65,6 @@ var import_sdk = require("@module-federation/sdk");
65
65
  var getPrefetchId = (id) => (0, import_sdk.encodeName)(`${id}/${import_sdk.MFPrefetchCommon.identifier}`);
66
66
 
67
67
  // src/cli/index.ts
68
- var addTemplate = (name) => `
69
- export default function () {
70
- let hasInit = false;
71
- return {
72
- name: 'data-prefetch-init-plugin',
73
- beforeInit(args) {
74
- if (!hasInit) {
75
- hasInit = true;
76
- globalThis.__FEDERATION__ = globalThis.__FEDERATION__ || {};
77
- globalThis.__FEDERATION__['${import_sdk2.MFPrefetchCommon.globalKey}'] = globalThis.__FEDERATION__['${import_sdk2.MFPrefetchCommon.globalKey}'] || {
78
- entryLoading: {},
79
- instance: new Map(),
80
- __PREFETCH_EXPORTS__: {},
81
- };
82
- globalThis.__FEDERATION__['${import_sdk2.MFPrefetchCommon.globalKey}']['${import_sdk2.MFPrefetchCommon.exportsKey}'] = globalThis.__FEDERATION__['${import_sdk2.MFPrefetchCommon.globalKey}']['${import_sdk2.MFPrefetchCommon.exportsKey}'] || {};
83
- globalThis.__FEDERATION__['${import_sdk2.MFPrefetchCommon.globalKey}']['${import_sdk2.MFPrefetchCommon.exportsKey}']['${name}'] = import('./bootstrap');
84
- }
85
- return args;
86
- }
87
- }
88
- }
89
- `;
90
68
  var PrefetchPlugin = class {
91
69
  constructor(options) {
92
70
  this.options = options;
@@ -100,6 +78,19 @@ var PrefetchPlugin = class {
100
78
  if (!compiler.options.context) {
101
79
  throw new Error("compiler.options.context is not defined");
102
80
  }
81
+ const { runtimePlugins } = this.options;
82
+ if (!Array.isArray(runtimePlugins)) {
83
+ this.options.runtimePlugins = [];
84
+ }
85
+ this.options.runtimePlugins.push(
86
+ import_path2.default.resolve(__dirname, "../esm/plugin.js")
87
+ );
88
+ this.options.runtimePlugins.push(
89
+ import_path2.default.resolve(__dirname, "../esm/shared/index.js")
90
+ );
91
+ if (!this.options.dataPrefetch) {
92
+ return;
93
+ }
103
94
  const prefetchs = [];
104
95
  const exposeAlias = Object.keys(exposes);
105
96
  exposeAlias.forEach((alias) => {
@@ -108,7 +99,7 @@ var PrefetchPlugin = class {
108
99
  if (typeof exposeValue === "string") {
109
100
  exposePath = exposeValue;
110
101
  } else {
111
- exposePath = exposeValue.import;
102
+ exposePath = exposeValue.import[0];
112
103
  }
113
104
  const targetPaths = fixPrefetchPath(exposePath);
114
105
  for (const pathItem of targetPaths) {
@@ -124,13 +115,6 @@ var PrefetchPlugin = class {
124
115
  }
125
116
  }
126
117
  });
127
- const { runtimePlugins } = this.options;
128
- if (!Array.isArray(runtimePlugins)) {
129
- this.options.runtimePlugins = [];
130
- }
131
- this.options.runtimePlugins.push(
132
- import_path2.default.resolve(__dirname, "../esm/plugin.js")
133
- );
134
118
  if (!this._reWriteExports) {
135
119
  return;
136
120
  }
@@ -151,12 +135,9 @@ var PrefetchPlugin = class {
151
135
  import_fs_extra2.default.mkdirSync(`${tempDirRealPath}/${encodedName}`);
152
136
  }
153
137
  import_fs_extra2.default.writeFileSync(asyncEntryPath, this._reWriteExports);
154
- const prefetchEntry = import_path2.default.resolve(
155
- compiler.options.context,
156
- `node_modules/${TEMP_DIR}/${encodedName}/${import_sdk2.MFPrefetchCommon.fileName}`
157
- );
158
- import_fs_extra2.default.writeFileSync(prefetchEntry, addTemplate(name));
159
- this.options.runtimePlugins.push(prefetchEntry);
138
+ new compiler.webpack.DefinePlugin({
139
+ FederationDataPrefetch: JSON.stringify(asyncEntryPath)
140
+ }).apply(compiler);
160
141
  }
161
142
  };
162
143
  // Annotate the CommonJS export names for ESM import in node:
@@ -9,11 +9,14 @@ 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 = [];
15
+ var strategy = "loaded-first";
16
+ var sharedFlag = strategy;
14
17
  var prefetchPlugin = () => ({
15
18
  name: "data-prefetch-runtime-plugin",
16
- afterResolve(options) {
19
+ initContainer(options) {
17
20
  const { remoteSnapshot, remoteInfo, id, origin } = options;
18
21
  const snapshot = remoteSnapshot;
19
22
  const { name } = remoteInfo;
@@ -27,6 +30,11 @@ var prefetchPlugin = () => ({
27
30
  if (!signal) {
28
31
  return options;
29
32
  }
33
+ if (sharedFlag !== strategy) {
34
+ throw new Error(
35
+ `[Module Federation Data Prefetch]: If you want to use data prefetch, the shared strategy must be 'loaded-first'`
36
+ );
37
+ }
30
38
  const instance = MFDataPrefetch.getInstance(name) || new MFDataPrefetch(prefetchOptions);
31
39
  let prefetchUrl;
32
40
  if (snapshot.prefetchEntry) {
@@ -41,20 +49,22 @@ var prefetchPlugin = () => ({
41
49
  if (projectExports instanceof Promise) {
42
50
  await projectExports;
43
51
  }
44
- const exports = instance.getExposeExports(id);
45
- logger_default.info(`1. Start Prefetch: ${id} - ${performance.now()}`);
46
- const result = Object.keys(exports).map((k) => {
47
- const value = instance.prefetch({
48
- id,
49
- functionId: k
52
+ return Promise.resolve().then(() => {
53
+ const exports = instance.getExposeExports(id);
54
+ logger_default.info(`1. Start Prefetch: ${id} - ${performance.now()}`);
55
+ const result = Object.keys(exports).map((k) => {
56
+ const value = instance.prefetch({
57
+ id,
58
+ functionId: k
59
+ });
60
+ const functionId = k;
61
+ return {
62
+ value,
63
+ functionId
64
+ };
50
65
  });
51
- const functionId = k;
52
- return {
53
- value,
54
- functionId
55
- };
66
+ return result;
56
67
  });
57
- return result;
58
68
  });
59
69
  loadingArray.push({
60
70
  id,
@@ -102,12 +112,29 @@ var prefetchPlugin = () => ({
102
112
  return options;
103
113
  }
104
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);
105
130
  const projectExports = instance.getProjectExports();
106
131
  if (projectExports instanceof Promise) {
107
132
  await projectExports;
108
133
  }
109
134
  const exports = instance.getExposeExports(id);
110
- logger_default.info(`1. Start Prefetch: ${id} - ${performance.now()}`);
135
+ logger_default.info(
136
+ `1. PreloadRemote Start Prefetch: ${id} - ${performance.now()}`
137
+ );
111
138
  const result = Object.keys(exports).map((k) => {
112
139
  const value = instance.prefetch({
113
140
  id,
@@ -126,6 +153,11 @@ var prefetchPlugin = () => ({
126
153
  promise
127
154
  });
128
155
  return options;
156
+ },
157
+ beforeLoadShare(options) {
158
+ const shareInfo = options.shareInfo;
159
+ sharedFlag = (shareInfo == null ? void 0 : shareInfo.strategy) || sharedFlag;
160
+ return options;
129
161
  }
130
162
  });
131
163
  var plugin_default = prefetchPlugin;
@@ -6,8 +6,7 @@ import {
6
6
  import path2 from "path";
7
7
  import fs2 from "fs-extra";
8
8
  import {
9
- encodeName,
10
- MFPrefetchCommon
9
+ encodeName
11
10
  } from "@module-federation/sdk";
12
11
 
13
12
  // src/common/constant.ts
@@ -38,28 +37,6 @@ var fixPrefetchPath = (exposePath) => {
38
37
  };
39
38
 
40
39
  // src/cli/index.ts
41
- var addTemplate = (name) => `
42
- export default function () {
43
- let hasInit = false;
44
- return {
45
- name: 'data-prefetch-init-plugin',
46
- beforeInit(args) {
47
- if (!hasInit) {
48
- hasInit = true;
49
- globalThis.__FEDERATION__ = globalThis.__FEDERATION__ || {};
50
- globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}'] = globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}'] || {
51
- entryLoading: {},
52
- instance: new Map(),
53
- __PREFETCH_EXPORTS__: {},
54
- };
55
- globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}']['${MFPrefetchCommon.exportsKey}'] = globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}']['${MFPrefetchCommon.exportsKey}'] || {};
56
- globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}']['${MFPrefetchCommon.exportsKey}']['${name}'] = import('./bootstrap');
57
- }
58
- return args;
59
- }
60
- }
61
- }
62
- `;
63
40
  var PrefetchPlugin = class {
64
41
  constructor(options) {
65
42
  this.options = options;
@@ -73,6 +50,19 @@ var PrefetchPlugin = class {
73
50
  if (!compiler.options.context) {
74
51
  throw new Error("compiler.options.context is not defined");
75
52
  }
53
+ const { runtimePlugins } = this.options;
54
+ if (!Array.isArray(runtimePlugins)) {
55
+ this.options.runtimePlugins = [];
56
+ }
57
+ this.options.runtimePlugins.push(
58
+ path2.resolve(__dirname, "../esm/plugin.js")
59
+ );
60
+ this.options.runtimePlugins.push(
61
+ path2.resolve(__dirname, "../esm/shared/index.js")
62
+ );
63
+ if (!this.options.dataPrefetch) {
64
+ return;
65
+ }
76
66
  const prefetchs = [];
77
67
  const exposeAlias = Object.keys(exposes);
78
68
  exposeAlias.forEach((alias) => {
@@ -81,7 +71,7 @@ var PrefetchPlugin = class {
81
71
  if (typeof exposeValue === "string") {
82
72
  exposePath = exposeValue;
83
73
  } else {
84
- exposePath = exposeValue.import;
74
+ exposePath = exposeValue.import[0];
85
75
  }
86
76
  const targetPaths = fixPrefetchPath(exposePath);
87
77
  for (const pathItem of targetPaths) {
@@ -97,13 +87,6 @@ var PrefetchPlugin = class {
97
87
  }
98
88
  }
99
89
  });
100
- const { runtimePlugins } = this.options;
101
- if (!Array.isArray(runtimePlugins)) {
102
- this.options.runtimePlugins = [];
103
- }
104
- this.options.runtimePlugins.push(
105
- path2.resolve(__dirname, "../esm/plugin.js")
106
- );
107
90
  if (!this._reWriteExports) {
108
91
  return;
109
92
  }
@@ -124,12 +107,9 @@ var PrefetchPlugin = class {
124
107
  fs2.mkdirSync(`${tempDirRealPath}/${encodedName}`);
125
108
  }
126
109
  fs2.writeFileSync(asyncEntryPath, this._reWriteExports);
127
- const prefetchEntry = path2.resolve(
128
- compiler.options.context,
129
- `node_modules/${TEMP_DIR}/${encodedName}/${MFPrefetchCommon.fileName}`
130
- );
131
- fs2.writeFileSync(prefetchEntry, addTemplate(name));
132
- this.options.runtimePlugins.push(prefetchEntry);
110
+ new compiler.webpack.DefinePlugin({
111
+ FederationDataPrefetch: JSON.stringify(asyncEntryPath)
112
+ }).apply(compiler);
133
113
  }
134
114
  };
135
115
  export {
package/dist/esm/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  prefetchPlugin
3
- } from "./chunk-BN3GGCE5.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-BN3GGCE5.js";
4
+ } from "./chunk-WLE6YNDH.js";
5
5
  import "./chunk-TTJJJ2WZ.js";
6
6
  import "./chunk-JEPJP5O3.js";
7
7
  import "./chunk-EWCGK4XA.js";
@@ -30,7 +30,7 @@ var usePrefetch = (options) => {
30
30
  if (isFirstMounted) {
31
31
  const startTiming = performance.now();
32
32
  logger_default.info(
33
- `2. Start Get Prefetch Data: ${options.id} - ${options.functionId} - ${startTiming}`
33
+ `2. Start Get Prefetch Data: ${options.id} - ${options.functionId || "default"} - ${startTiming}`
34
34
  );
35
35
  }
36
36
  const { id, functionId, deferId } = options;
@@ -59,7 +59,7 @@ var usePrefetch = (options) => {
59
59
  useEffect2(() => {
60
60
  const useEffectTiming = performance.now();
61
61
  logger_default.info(
62
- `3. Start Execute UseEffect: ${options.id} - ${options.functionId} - ${useEffectTiming}`
62
+ `3. Start Execute UseEffect: ${options.id} - ${options.functionId || "default"} - ${useEffectTiming}`
63
63
  );
64
64
  return () => {
65
65
  prefetchInstance == null ? void 0 : prefetchInstance.markOutdate(prefetchInfo, true);
@@ -0,0 +1,25 @@
1
+ // src/shared/index.ts
2
+ var sharedStrategy = () => ({
3
+ name: "shared-strategy",
4
+ beforeInit(args) {
5
+ const { userOptions } = args;
6
+ const shared = userOptions.shared;
7
+ if (shared) {
8
+ Object.keys(shared).forEach((sharedKey) => {
9
+ const sharedConfigs = shared[sharedKey];
10
+ const arraySharedConfigs = Array.isArray(sharedConfigs) ? sharedConfigs : [sharedConfigs];
11
+ arraySharedConfigs.forEach((s) => {
12
+ s.strategy = "loaded-first";
13
+ });
14
+ });
15
+ console.warn(
16
+ `[Module Federation Data Prefetch]: Your shared strategy is set to 'loaded-first', this is a necessary condition for data prefetch`
17
+ );
18
+ }
19
+ return args;
20
+ }
21
+ });
22
+ var shared_default = sharedStrategy;
23
+ export {
24
+ shared_default as default
25
+ };