@module-federation/data-prefetch 0.0.0-next-20241231075249 → 0.0.0-next-20250106035038
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/package.json +19 -14
- package/.swcrc +0 -29
- package/CHANGELOG.md +0 -246
- package/__tests__/babel.spec.ts +0 -75
- package/__tests__/prefetch.spec.ts +0 -139
- package/__tests__/react.spec.ts +0 -119
- package/jest.config.js +0 -29
- package/project.json +0 -64
- package/rollup.config.js +0 -63
- package/src/cli/babel.ts +0 -94
- package/src/cli/index.ts +0 -176
- package/src/common/constant.ts +0 -1
- package/src/common/index.ts +0 -1
- package/src/common/node-utils.ts +0 -24
- package/src/common/runtime-utils.ts +0 -34
- package/src/constant.ts +0 -1
- package/src/index.ts +0 -2
- package/src/logger/index.ts +0 -5
- package/src/plugin.ts +0 -191
- package/src/prefetch.ts +0 -216
- package/src/react/hooks.ts +0 -95
- package/src/react/index.ts +0 -1
- package/src/react/utils.ts +0 -11
- package/src/universal/index.ts +0 -27
- package/tsconfig.json +0 -27
- package/tsconfig.lib.json +0 -10
package/jest.config.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// For a detailed explanation regarding each configuration property, visit:
|
|
2
|
-
// https://jestjs.io/docs/en/configuration.html
|
|
3
|
-
|
|
4
|
-
module.exports = {
|
|
5
|
-
clearMocks: true,
|
|
6
|
-
cacheDirectory: './jest/cache',
|
|
7
|
-
coverageDirectory: './jest/coverage',
|
|
8
|
-
testEnvironment: 'jsdom',
|
|
9
|
-
coveragePathIgnorePatterns: ['__tests__', '/node_modules/'],
|
|
10
|
-
coverageProvider: 'v8',
|
|
11
|
-
coverageReporters: ['cobertura', 'clover', 'json', 'lcov', 'text'],
|
|
12
|
-
globals: {
|
|
13
|
-
__DEV__: true,
|
|
14
|
-
__TEST__: true,
|
|
15
|
-
__BROWSER__: false,
|
|
16
|
-
__VERSION__: '"unknow"',
|
|
17
|
-
},
|
|
18
|
-
preset: 'ts-jest',
|
|
19
|
-
transformIgnorePatterns: [
|
|
20
|
-
// Change MODULE_NAME_HERE to your module that isn't being compiled
|
|
21
|
-
'/node_modules/(?!((@byted/garfish-)|(byted-tea-sdk))).+\\.js$',
|
|
22
|
-
],
|
|
23
|
-
transform: {
|
|
24
|
-
'^.+\\.(t|j)sx?$': ['@swc/jest', { swcrc: false }],
|
|
25
|
-
},
|
|
26
|
-
rootDir: __dirname,
|
|
27
|
-
testMatch: ['<rootDir>/__tests__/**/*.spec.[jt]s?(x)'],
|
|
28
|
-
testPathIgnorePatterns: ['/node_modules/'],
|
|
29
|
-
};
|
package/project.json
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "data-prefetch",
|
|
3
|
-
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
-
"sourceRoot": "packages/data-prefetch/src",
|
|
5
|
-
"projectType": "library",
|
|
6
|
-
"tags": ["type:pkg"],
|
|
7
|
-
"targets": {
|
|
8
|
-
"build": {
|
|
9
|
-
"executor": "@nx/rollup:rollup",
|
|
10
|
-
"outputs": ["{options.outputPath}"],
|
|
11
|
-
"options": {
|
|
12
|
-
"outputPath": "packages/data-prefetch/dist",
|
|
13
|
-
"main": "packages/data-prefetch/src/index.ts",
|
|
14
|
-
"tsConfig": "packages/data-prefetch/tsconfig.lib.json",
|
|
15
|
-
"assets": [],
|
|
16
|
-
"project": "packages/data-prefetch/package.json",
|
|
17
|
-
"rollupConfig": "packages/data-prefetch/rollup.config.js",
|
|
18
|
-
"compiler": "swc",
|
|
19
|
-
"format": ["cjs", "esm"],
|
|
20
|
-
"generatePackageJson": false
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
"test": {
|
|
24
|
-
"executor": "@nx/jest:jest",
|
|
25
|
-
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
|
26
|
-
"options": {
|
|
27
|
-
"jestConfig": "packages/data-prefetch/jest.config.js",
|
|
28
|
-
"passWithNoTests": true
|
|
29
|
-
},
|
|
30
|
-
"configurations": {
|
|
31
|
-
"ci": {
|
|
32
|
-
"ci": true,
|
|
33
|
-
"codeCoverage": true
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
"lint": {
|
|
38
|
-
"executor": "@nx/eslint:lint",
|
|
39
|
-
"outputs": ["{options.outputFile}"],
|
|
40
|
-
"options": {
|
|
41
|
-
"lintFilePatterns": [
|
|
42
|
-
"packages/data-prefetch/**/*.ts",
|
|
43
|
-
"packages/data-prefetch/package.json"
|
|
44
|
-
]
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
"pre-release": {
|
|
48
|
-
"executor": "nx:run-commands",
|
|
49
|
-
"options": {
|
|
50
|
-
"parallel": false,
|
|
51
|
-
"commands": [
|
|
52
|
-
{
|
|
53
|
-
"command": "nx run data-prefetch:test",
|
|
54
|
-
"forwardAllArgs": false
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
"command": "nx run data-prefetch:build",
|
|
58
|
-
"forwardAllArgs": false
|
|
59
|
-
}
|
|
60
|
-
]
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
package/rollup.config.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
const copy = require('rollup-plugin-copy');
|
|
2
|
-
|
|
3
|
-
module.exports = (rollupConfig, _projectOptions) => {
|
|
4
|
-
rollupConfig.plugins.push(
|
|
5
|
-
copy({
|
|
6
|
-
targets: [
|
|
7
|
-
{
|
|
8
|
-
src: 'packages/data-prefetch/LICENSE',
|
|
9
|
-
dest: 'packages/data-prefetch/dist',
|
|
10
|
-
},
|
|
11
|
-
],
|
|
12
|
-
}),
|
|
13
|
-
);
|
|
14
|
-
rollupConfig.input = {
|
|
15
|
-
index: 'packages/data-prefetch/src/index.ts',
|
|
16
|
-
react: 'packages/data-prefetch/src/react/index.ts',
|
|
17
|
-
cli: 'packages/data-prefetch/src/cli/index.ts',
|
|
18
|
-
babel: 'packages/data-prefetch/src/cli/babel.ts',
|
|
19
|
-
universal: 'packages/data-prefetch/src/universal/index.ts',
|
|
20
|
-
plugin: 'packages/data-prefetch/src/plugin.ts',
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
if (Array.isArray(rollupConfig.output)) {
|
|
24
|
-
rollupConfig.output = rollupConfig.output.map((c) => ({
|
|
25
|
-
...c,
|
|
26
|
-
manualChunks: (id) => {
|
|
27
|
-
if (id.includes('@swc/helpers')) {
|
|
28
|
-
return 'polyfills';
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
hoistTransitiveImports: false,
|
|
32
|
-
entryFileNames:
|
|
33
|
-
c.format === 'esm'
|
|
34
|
-
? c.entryFileNames.replace('.js', '.mjs')
|
|
35
|
-
: c.entryFileNames,
|
|
36
|
-
chunkFileNames:
|
|
37
|
-
c.format === 'esm'
|
|
38
|
-
? c.chunkFileNames.replace('.js', '.mjs')
|
|
39
|
-
: c.chunkFileNames,
|
|
40
|
-
}));
|
|
41
|
-
} else {
|
|
42
|
-
rollupConfig.output = {
|
|
43
|
-
...rollupConfig.output,
|
|
44
|
-
manualChunks: (id) => {
|
|
45
|
-
if (id.includes('@swc/helpers')) {
|
|
46
|
-
return 'polyfills';
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
hoistTransitiveImports: false,
|
|
50
|
-
entryFileNames:
|
|
51
|
-
rollupConfig.output.format === 'esm'
|
|
52
|
-
? rollupConfig.output.entryFileNames.replace('.js', '.mjs')
|
|
53
|
-
: rollupConfig.output.entryFileNames,
|
|
54
|
-
chunkFileNames:
|
|
55
|
-
rollupConfig.output.format === 'esm'
|
|
56
|
-
? rollupConfig.output.chunkFileNames.replace('.js', '.mjs')
|
|
57
|
-
: rollupConfig.output.chunkFileNames,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// rollupConfig.external = [/@module-federation/];
|
|
62
|
-
return rollupConfig;
|
|
63
|
-
};
|
package/src/cli/babel.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
// no used now
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import type { moduleFederationPlugin } from '@module-federation/sdk';
|
|
4
|
-
|
|
5
|
-
const attribute = 'id';
|
|
6
|
-
const hookId = 'usePrefetch';
|
|
7
|
-
const importPackage = '@module-federation/data-prefetch/react';
|
|
8
|
-
|
|
9
|
-
interface BabelPluginOptions {
|
|
10
|
-
hook_id: string;
|
|
11
|
-
import_pkg: string;
|
|
12
|
-
attribute: string;
|
|
13
|
-
name: string;
|
|
14
|
-
exposes: moduleFederationPlugin.ModuleFederationPluginOptions['exposes'];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
18
|
-
export default (babel: { types: any }, options: BabelPluginOptions) => {
|
|
19
|
-
const t = babel.types;
|
|
20
|
-
let shouldHandle = false;
|
|
21
|
-
let scope = '';
|
|
22
|
-
const { name, exposes } = options;
|
|
23
|
-
if (!exposes) {
|
|
24
|
-
return {};
|
|
25
|
-
}
|
|
26
|
-
const exposesKey = Object.keys(exposes);
|
|
27
|
-
const processedExposes = exposesKey.map((expose) => ({
|
|
28
|
-
key: expose.replace('.', ''),
|
|
29
|
-
value: path.resolve(
|
|
30
|
-
// @ts-ignore
|
|
31
|
-
typeof exposes[expose] === 'string'
|
|
32
|
-
? // @ts-ignore
|
|
33
|
-
exposes[expose]
|
|
34
|
-
: // @ts-ignore
|
|
35
|
-
exposes[expose].import,
|
|
36
|
-
),
|
|
37
|
-
}));
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
visitor: {
|
|
41
|
-
ImportDeclaration(
|
|
42
|
-
nodePath: {
|
|
43
|
-
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
44
|
-
node: { source: { value: any }; specifiers: any };
|
|
45
|
-
},
|
|
46
|
-
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
47
|
-
state: { file: { opts: { filename: any } } },
|
|
48
|
-
) {
|
|
49
|
-
const source = nodePath.node.source.value;
|
|
50
|
-
const { specifiers } = nodePath.node;
|
|
51
|
-
const { filename } = state.file.opts;
|
|
52
|
-
|
|
53
|
-
if (source === importPackage) {
|
|
54
|
-
shouldHandle = specifiers.some(
|
|
55
|
-
(specifier: { imported: { name: string } }) =>
|
|
56
|
-
specifier.imported &&
|
|
57
|
-
specifier.imported.name === hookId &&
|
|
58
|
-
processedExposes.find(
|
|
59
|
-
// biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
|
|
60
|
-
(expose) => expose.value === filename && (scope = expose.key),
|
|
61
|
-
),
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
CallExpression(nodePath: {
|
|
67
|
-
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
68
|
-
node: { callee: any; arguments: string | any[] };
|
|
69
|
-
}) {
|
|
70
|
-
if (
|
|
71
|
-
shouldHandle &&
|
|
72
|
-
t.isIdentifier(nodePath.node.callee, { name: hookId }) &&
|
|
73
|
-
nodePath.node.arguments.length > 0
|
|
74
|
-
) {
|
|
75
|
-
const objectExpression = nodePath.node.arguments[0];
|
|
76
|
-
if (
|
|
77
|
-
objectExpression &&
|
|
78
|
-
t.isObjectExpression(objectExpression) &&
|
|
79
|
-
!objectExpression.properties.find(
|
|
80
|
-
(p: { key: { name: string } }) => p.key.name === attribute,
|
|
81
|
-
)
|
|
82
|
-
) {
|
|
83
|
-
objectExpression.properties.push(
|
|
84
|
-
t.objectProperty(
|
|
85
|
-
t.identifier(attribute),
|
|
86
|
-
t.stringLiteral(name + scope),
|
|
87
|
-
),
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
};
|
package/src/cli/index.ts
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import fs from 'fs-extra';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
encodeName,
|
|
6
|
-
moduleFederationPlugin,
|
|
7
|
-
MFPrefetchCommon,
|
|
8
|
-
} from '@module-federation/sdk';
|
|
9
|
-
import { normalizeWebpackPath } from '@module-federation/sdk/normalize-webpack-path';
|
|
10
|
-
import type { Compiler, WebpackPluginInstance } from 'webpack';
|
|
11
|
-
|
|
12
|
-
import { TEMP_DIR } from '../common/constant';
|
|
13
|
-
import { fileExistsWithCaseSync, fixPrefetchPath } from '../common/node-utils';
|
|
14
|
-
import { getPrefetchId } from '../common/runtime-utils';
|
|
15
|
-
import { SHARED_STRATEGY } from '../constant';
|
|
16
|
-
|
|
17
|
-
const { RuntimeGlobals, Template } = require(
|
|
18
|
-
normalizeWebpackPath('webpack'),
|
|
19
|
-
) as typeof import('webpack');
|
|
20
|
-
|
|
21
|
-
export function getFederationGlobalScope(
|
|
22
|
-
runtimeGlobals: typeof RuntimeGlobals,
|
|
23
|
-
): string {
|
|
24
|
-
return `${runtimeGlobals.require || '__webpack_require__'}.federation`;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export class PrefetchPlugin implements WebpackPluginInstance {
|
|
28
|
-
public options: moduleFederationPlugin.ModuleFederationPluginOptions;
|
|
29
|
-
private _reWriteExports: string;
|
|
30
|
-
|
|
31
|
-
constructor(options: moduleFederationPlugin.ModuleFederationPluginOptions) {
|
|
32
|
-
this.options = options;
|
|
33
|
-
this._reWriteExports = '';
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// eslint-disable-next-line max-lines-per-function
|
|
37
|
-
apply(compiler: Compiler) {
|
|
38
|
-
const { name, exposes } = this.options;
|
|
39
|
-
if (!exposes) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
if (!compiler.options.context) {
|
|
43
|
-
throw new Error('compiler.options.context is not defined');
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const { runtimePlugins } = this.options;
|
|
47
|
-
if (!Array.isArray(runtimePlugins)) {
|
|
48
|
-
this.options.runtimePlugins = [];
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const runtimePath = path.resolve(__dirname, './plugin.esm.mjs');
|
|
52
|
-
if (!this.options.runtimePlugins?.includes(runtimePath)) {
|
|
53
|
-
this.options.runtimePlugins!.push(runtimePath);
|
|
54
|
-
}
|
|
55
|
-
if (this.options.shareStrategy !== SHARED_STRATEGY) {
|
|
56
|
-
this.options.shareStrategy = SHARED_STRATEGY;
|
|
57
|
-
console.warn(
|
|
58
|
-
`[Module Federation Data Prefetch]: Your shared strategy is set to '${SHARED_STRATEGY}', this is a necessary condition for data prefetch`,
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const encodedName = encodeName(name as string);
|
|
63
|
-
const asyncEntryPath = path.resolve(
|
|
64
|
-
compiler.options.context,
|
|
65
|
-
`node_modules/${TEMP_DIR}/${encodedName}/bootstrap.js`,
|
|
66
|
-
);
|
|
67
|
-
if (fs.existsSync(asyncEntryPath)) {
|
|
68
|
-
fs.unlinkSync(asyncEntryPath);
|
|
69
|
-
}
|
|
70
|
-
if (!this.options.dataPrefetch) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const prefetchs: Array<string> = [];
|
|
75
|
-
const exposeAlias = Object.keys(exposes);
|
|
76
|
-
exposeAlias.forEach((alias) => {
|
|
77
|
-
let exposePath;
|
|
78
|
-
// @ts-ignore
|
|
79
|
-
const exposeValue = exposes[alias];
|
|
80
|
-
if (typeof exposeValue === 'string') {
|
|
81
|
-
exposePath = exposeValue;
|
|
82
|
-
} else {
|
|
83
|
-
exposePath = exposeValue.import[0];
|
|
84
|
-
}
|
|
85
|
-
const targetPaths = fixPrefetchPath(exposePath);
|
|
86
|
-
for (const pathItem of targetPaths) {
|
|
87
|
-
const absolutePath = path.resolve(compiler.options.context!, pathItem);
|
|
88
|
-
if (fileExistsWithCaseSync(absolutePath)) {
|
|
89
|
-
prefetchs.push(pathItem);
|
|
90
|
-
const absoluteAlias = alias.replace('.', '');
|
|
91
|
-
this._reWriteExports += `export * as ${getPrefetchId(
|
|
92
|
-
`${name}${absoluteAlias}`,
|
|
93
|
-
)} from '${absolutePath}';\n`;
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
if (!this._reWriteExports) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
const tempDirRealPath = path.resolve(
|
|
103
|
-
compiler.options.context,
|
|
104
|
-
'node_modules',
|
|
105
|
-
TEMP_DIR,
|
|
106
|
-
);
|
|
107
|
-
if (!fs.existsSync(tempDirRealPath)) {
|
|
108
|
-
fs.mkdirSync(tempDirRealPath);
|
|
109
|
-
}
|
|
110
|
-
if (!fs.existsSync(`${tempDirRealPath}/${encodedName}`)) {
|
|
111
|
-
fs.mkdirSync(`${tempDirRealPath}/${encodedName}`);
|
|
112
|
-
}
|
|
113
|
-
fs.writeFileSync(asyncEntryPath, this._reWriteExports);
|
|
114
|
-
new compiler.webpack.DefinePlugin({
|
|
115
|
-
FederationDataPrefetch: JSON.stringify(asyncEntryPath),
|
|
116
|
-
}).apply(compiler);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
static addRuntime(
|
|
120
|
-
compiler: Compiler,
|
|
121
|
-
options: {
|
|
122
|
-
name: string;
|
|
123
|
-
},
|
|
124
|
-
) {
|
|
125
|
-
const encodedName = encodeName(options.name as string);
|
|
126
|
-
if (!compiler.options.context) {
|
|
127
|
-
throw new Error('compiler.options.context is not defined');
|
|
128
|
-
}
|
|
129
|
-
const prefetchEntry = path.resolve(
|
|
130
|
-
compiler.options.context,
|
|
131
|
-
`node_modules/.mf/${encodedName}/bootstrap.js`,
|
|
132
|
-
);
|
|
133
|
-
const federationGlobal = getFederationGlobalScope(
|
|
134
|
-
RuntimeGlobals || ({} as typeof RuntimeGlobals),
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
return Template.asString([
|
|
138
|
-
fs.existsSync(prefetchEntry)
|
|
139
|
-
? Template.indent([
|
|
140
|
-
'function injectPrefetch() {',
|
|
141
|
-
Template.indent([
|
|
142
|
-
`globalThis.__FEDERATION__ = globalThis.__FEDERATION__ || {};`,
|
|
143
|
-
`globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}'] = globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}'] || {`,
|
|
144
|
-
`entryLoading: {},`,
|
|
145
|
-
`instance: new Map(),`,
|
|
146
|
-
`__PREFETCH_EXPORTS__: {},`,
|
|
147
|
-
`};`,
|
|
148
|
-
`globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}']['${MFPrefetchCommon.exportsKey}'] = globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}']['${MFPrefetchCommon.exportsKey}'] || {};`,
|
|
149
|
-
`globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}']['${MFPrefetchCommon.exportsKey}']['${options.name}'] = function(){ return import('${prefetchEntry}');}`,
|
|
150
|
-
]),
|
|
151
|
-
'}',
|
|
152
|
-
`${federationGlobal}.prefetch = injectPrefetch`,
|
|
153
|
-
])
|
|
154
|
-
: '',
|
|
155
|
-
Template.indent([
|
|
156
|
-
`if(!${federationGlobal}.isMFRemote && ${federationGlobal}.prefetch){`,
|
|
157
|
-
`${federationGlobal}.prefetch()`,
|
|
158
|
-
'}',
|
|
159
|
-
]),
|
|
160
|
-
]);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
static setRemoteIdentifier() {
|
|
164
|
-
const federationGlobal = getFederationGlobalScope(
|
|
165
|
-
RuntimeGlobals || ({} as typeof RuntimeGlobals),
|
|
166
|
-
);
|
|
167
|
-
return Template.indent([`${federationGlobal}.isMFRemote = true;`]);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
static removeRemoteIdentifier() {
|
|
171
|
-
const federationGlobal = getFederationGlobalScope(
|
|
172
|
-
RuntimeGlobals || ({} as typeof RuntimeGlobals),
|
|
173
|
-
);
|
|
174
|
-
return Template.indent([`${federationGlobal}.isMFRemote = false;`]);
|
|
175
|
-
}
|
|
176
|
-
}
|
package/src/common/constant.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const TEMP_DIR = '.mf';
|
package/src/common/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './constant';
|
package/src/common/node-utils.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import fs from 'fs-extra';
|
|
3
|
-
|
|
4
|
-
export const fileExistsWithCaseSync = (filepath: string): boolean => {
|
|
5
|
-
const dir = path.dirname(filepath);
|
|
6
|
-
if (filepath === '/' || filepath === '.') {
|
|
7
|
-
return true;
|
|
8
|
-
}
|
|
9
|
-
const filenames = fs.readdirSync(dir);
|
|
10
|
-
if (filenames.indexOf(path.basename(filepath)) === -1) {
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
13
|
-
return fileExistsWithCaseSync(dir);
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export const fixPrefetchPath = (exposePath: string): Array<string> => {
|
|
17
|
-
const pathExt = ['.js', '.ts'];
|
|
18
|
-
const extReg = /\.(ts|js|tsx|jsx)$/;
|
|
19
|
-
if (extReg.test(exposePath)) {
|
|
20
|
-
return pathExt.map((ext) => exposePath.replace(extReg, `.prefetch${ext}`));
|
|
21
|
-
} else {
|
|
22
|
-
return pathExt.map((ext) => exposePath + `.prefetch${ext}`);
|
|
23
|
-
}
|
|
24
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { getInstance } from '@module-federation/runtime';
|
|
2
|
-
import {
|
|
3
|
-
encodeName,
|
|
4
|
-
ModuleInfo,
|
|
5
|
-
MFPrefetchCommon,
|
|
6
|
-
} from '@module-federation/sdk';
|
|
7
|
-
|
|
8
|
-
export const getScope = (): string => {
|
|
9
|
-
return getInstance()!.options.name;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export const getPrefetchId = (id: string): string =>
|
|
13
|
-
encodeName(`${id}/${MFPrefetchCommon.identifier}`);
|
|
14
|
-
|
|
15
|
-
export const compatGetPrefetchId = (id: string): string =>
|
|
16
|
-
encodeName(`${id}/VmokPrefetch`);
|
|
17
|
-
|
|
18
|
-
export const getSignalFromManifest = (remoteSnapshot: ModuleInfo): boolean => {
|
|
19
|
-
if (!remoteSnapshot) {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (
|
|
24
|
-
!('prefetchEntry' in remoteSnapshot) &&
|
|
25
|
-
!('prefetchInterface' in remoteSnapshot)
|
|
26
|
-
) {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (!remoteSnapshot.prefetchEntry && !remoteSnapshot.prefetchInterface) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
return true;
|
|
34
|
-
};
|
package/src/constant.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const SHARED_STRATEGY = 'loaded-first';
|
package/src/index.ts
DELETED
package/src/logger/index.ts
DELETED
package/src/plugin.ts
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import type { FederationRuntimePlugin } from '@module-federation/runtime/types';
|
|
2
|
-
import { ModuleInfo, getResourceUrl } from '@module-federation/sdk';
|
|
3
|
-
|
|
4
|
-
import { getSignalFromManifest } from './common/runtime-utils';
|
|
5
|
-
import { MFDataPrefetch } from './prefetch';
|
|
6
|
-
import logger from './logger';
|
|
7
|
-
import { SHARED_STRATEGY } from './constant';
|
|
8
|
-
|
|
9
|
-
interface Loading {
|
|
10
|
-
id: string;
|
|
11
|
-
promise: Promise<
|
|
12
|
-
Array<{
|
|
13
|
-
value: any;
|
|
14
|
-
functionId: string;
|
|
15
|
-
}>
|
|
16
|
-
>;
|
|
17
|
-
}
|
|
18
|
-
const loadingArray: Array<Loading> = [];
|
|
19
|
-
let sharedFlag = SHARED_STRATEGY;
|
|
20
|
-
// eslint-disable-next-line max-lines-per-function
|
|
21
|
-
export const prefetchPlugin = (): FederationRuntimePlugin => ({
|
|
22
|
-
name: 'data-prefetch-runtime-plugin',
|
|
23
|
-
initContainer(options) {
|
|
24
|
-
const { remoteSnapshot, remoteInfo, id, origin } = options;
|
|
25
|
-
const snapshot = remoteSnapshot as ModuleInfo;
|
|
26
|
-
const { name } = remoteInfo;
|
|
27
|
-
|
|
28
|
-
const prefetchOptions = {
|
|
29
|
-
name,
|
|
30
|
-
remote: remoteInfo,
|
|
31
|
-
origin,
|
|
32
|
-
remoteSnapshot: snapshot,
|
|
33
|
-
};
|
|
34
|
-
const signal = getSignalFromManifest(snapshot);
|
|
35
|
-
if (!signal) {
|
|
36
|
-
return options;
|
|
37
|
-
}
|
|
38
|
-
if (sharedFlag !== SHARED_STRATEGY) {
|
|
39
|
-
throw new Error(
|
|
40
|
-
`[Module Federation Data Prefetch]: If you want to use data prefetch, the shared strategy must be 'loaded-first'`,
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const instance =
|
|
45
|
-
MFDataPrefetch.getInstance(name) || new MFDataPrefetch(prefetchOptions);
|
|
46
|
-
|
|
47
|
-
let prefetchUrl;
|
|
48
|
-
// @ts-expect-error
|
|
49
|
-
if (snapshot.prefetchEntry) {
|
|
50
|
-
// @ts-expect-error
|
|
51
|
-
prefetchUrl = getResourceUrl(snapshot, snapshot.prefetchEntry as string);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const exist = loadingArray.find((loading) => loading.id === id);
|
|
55
|
-
if (exist) {
|
|
56
|
-
return options;
|
|
57
|
-
}
|
|
58
|
-
const promise = instance.loadEntry(prefetchUrl).then(async () => {
|
|
59
|
-
const projectExports = instance!.getProjectExports();
|
|
60
|
-
if (projectExports instanceof Promise) {
|
|
61
|
-
await projectExports;
|
|
62
|
-
}
|
|
63
|
-
return Promise.resolve().then(() => {
|
|
64
|
-
const exports = instance!.getExposeExports(id);
|
|
65
|
-
logger.info(
|
|
66
|
-
`1. Start Prefetch initContainer: ${id} - ${performance.now()}`,
|
|
67
|
-
);
|
|
68
|
-
const result = Object.keys(exports).map((k) => {
|
|
69
|
-
const value = instance!.prefetch({
|
|
70
|
-
id,
|
|
71
|
-
functionId: k,
|
|
72
|
-
});
|
|
73
|
-
const functionId = k;
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
value,
|
|
77
|
-
functionId,
|
|
78
|
-
};
|
|
79
|
-
});
|
|
80
|
-
return result;
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
loadingArray.push({
|
|
85
|
-
id,
|
|
86
|
-
promise,
|
|
87
|
-
});
|
|
88
|
-
return options;
|
|
89
|
-
},
|
|
90
|
-
|
|
91
|
-
afterResolve(options) {
|
|
92
|
-
const { remoteSnapshot, remoteInfo, id, origin } = options;
|
|
93
|
-
const snapshot = remoteSnapshot as ModuleInfo;
|
|
94
|
-
const { name } = remoteInfo;
|
|
95
|
-
|
|
96
|
-
const prefetchOptions = {
|
|
97
|
-
name,
|
|
98
|
-
remote: remoteInfo,
|
|
99
|
-
origin,
|
|
100
|
-
remoteSnapshot: snapshot,
|
|
101
|
-
};
|
|
102
|
-
const signal = getSignalFromManifest(snapshot);
|
|
103
|
-
if (!signal) {
|
|
104
|
-
return options;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const inited = loadingArray.some((info) => info.id === id);
|
|
108
|
-
if (!inited) {
|
|
109
|
-
return options;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (sharedFlag !== SHARED_STRATEGY) {
|
|
113
|
-
throw new Error(
|
|
114
|
-
`[Module Federation Data Prefetch]: If you want to use data prefetch, the shared strategy must be 'loaded-first'`,
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const instance =
|
|
119
|
-
MFDataPrefetch.getInstance(name) || new MFDataPrefetch(prefetchOptions);
|
|
120
|
-
|
|
121
|
-
let prefetchUrl;
|
|
122
|
-
// @ts-expect-error
|
|
123
|
-
if (snapshot.prefetchEntry) {
|
|
124
|
-
// @ts-expect-error
|
|
125
|
-
prefetchUrl = getResourceUrl(snapshot, snapshot.prefetchEntry as string);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const index = loadingArray.findIndex((loading) => loading.id === id);
|
|
129
|
-
// clear cache
|
|
130
|
-
if (index !== -1) {
|
|
131
|
-
loadingArray.splice(index, 1);
|
|
132
|
-
}
|
|
133
|
-
const promise = instance.loadEntry(prefetchUrl).then(async () => {
|
|
134
|
-
const projectExports = instance!.getProjectExports();
|
|
135
|
-
if (projectExports instanceof Promise) {
|
|
136
|
-
await projectExports;
|
|
137
|
-
}
|
|
138
|
-
return Promise.resolve().then(() => {
|
|
139
|
-
const exports = instance!.getExposeExports(id);
|
|
140
|
-
logger.info(
|
|
141
|
-
`1. Start Prefetch afterResolve: ${id} - ${performance.now()}`,
|
|
142
|
-
);
|
|
143
|
-
const result = Object.keys(exports).map((k) => {
|
|
144
|
-
const value = instance!.prefetch({
|
|
145
|
-
id,
|
|
146
|
-
functionId: k,
|
|
147
|
-
});
|
|
148
|
-
const functionId = k;
|
|
149
|
-
|
|
150
|
-
return {
|
|
151
|
-
value,
|
|
152
|
-
functionId,
|
|
153
|
-
};
|
|
154
|
-
});
|
|
155
|
-
return result;
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
loadingArray.push({
|
|
160
|
-
id,
|
|
161
|
-
promise,
|
|
162
|
-
});
|
|
163
|
-
return options;
|
|
164
|
-
},
|
|
165
|
-
async onLoad(options) {
|
|
166
|
-
const { remote, id } = options;
|
|
167
|
-
const { name } = remote;
|
|
168
|
-
const promise = loadingArray.find((loading) => loading.id === id)?.promise;
|
|
169
|
-
|
|
170
|
-
if (promise) {
|
|
171
|
-
const prefetch = await promise;
|
|
172
|
-
const prefetchValue = prefetch.map((result) => result.value);
|
|
173
|
-
await Promise.all(prefetchValue);
|
|
174
|
-
const instance = MFDataPrefetch.getInstance(name);
|
|
175
|
-
|
|
176
|
-
prefetch.forEach((result: { value: any; functionId: string }) => {
|
|
177
|
-
const { value, functionId } = result;
|
|
178
|
-
instance!.memorize(id + functionId, value);
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
return options;
|
|
182
|
-
},
|
|
183
|
-
|
|
184
|
-
beforeLoadShare(options) {
|
|
185
|
-
const shareInfo = options.shareInfo;
|
|
186
|
-
sharedFlag = shareInfo?.strategy || sharedFlag;
|
|
187
|
-
return options;
|
|
188
|
-
},
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
export default prefetchPlugin;
|