@module-federation/bridge-react 0.2.5 → 0.2.6
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 +6 -0
- package/dist/index.cjs.js +82 -75
- package/dist/index.es.js +83 -76
- package/package.json +2 -2
- package/src/create.tsx +62 -180
- package/src/remote/index.tsx +165 -0
package/CHANGELOG.md
CHANGED
package/dist/index.cjs.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const React = require("react");
|
|
4
|
-
const ReactRouterDOM = require("react-router-dom");
|
|
5
4
|
const context = require("./context--mtFt3tp.cjs");
|
|
5
|
+
const ReactRouterDOM = require("react-router-dom");
|
|
6
6
|
const ReactDOM = require("react-dom");
|
|
7
7
|
function _interopNamespaceDefault(e) {
|
|
8
8
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
@@ -122,26 +122,11 @@ const RemoteApp = ({
|
|
|
122
122
|
memoryRoute,
|
|
123
123
|
basename,
|
|
124
124
|
providerInfo,
|
|
125
|
-
dispathPopstate,
|
|
126
125
|
...resProps
|
|
127
126
|
}) => {
|
|
128
127
|
const rootRef = React.useRef(null);
|
|
129
128
|
const renderDom = React.useRef(null);
|
|
130
129
|
const providerInfoRef = React.useRef(null);
|
|
131
|
-
if (dispathPopstate) {
|
|
132
|
-
const location = ReactRouterDOM__namespace.useLocation();
|
|
133
|
-
const [pathname, setPathname] = React.useState(location.pathname);
|
|
134
|
-
React.useEffect(() => {
|
|
135
|
-
if (pathname !== "" && pathname !== location.pathname) {
|
|
136
|
-
context.LoggerInstance.log(`createRemoteComponent dispatchPopstateEnv >>>`, {
|
|
137
|
-
name,
|
|
138
|
-
pathname: location.pathname
|
|
139
|
-
});
|
|
140
|
-
context.f();
|
|
141
|
-
}
|
|
142
|
-
setPathname(location.pathname);
|
|
143
|
-
}, [location]);
|
|
144
|
-
}
|
|
145
130
|
React.useEffect(() => {
|
|
146
131
|
const renderTimeout = setTimeout(() => {
|
|
147
132
|
const providerReturn = providerInfo();
|
|
@@ -178,12 +163,10 @@ const RemoteApp = ({
|
|
|
178
163
|
}, []);
|
|
179
164
|
return /* @__PURE__ */ React.createElement("div", { ref: rootRef });
|
|
180
165
|
};
|
|
181
|
-
RemoteApp["__APP_VERSION__"] = "0.2.
|
|
182
|
-
function
|
|
166
|
+
RemoteApp["__APP_VERSION__"] = "0.2.6";
|
|
167
|
+
function withRouterData(WrappedComponent) {
|
|
183
168
|
return (props) => {
|
|
184
169
|
var _a;
|
|
185
|
-
const exportName = (info == null ? void 0 : info.export) || "default";
|
|
186
|
-
let basename = "/";
|
|
187
170
|
let enableDispathPopstate = false;
|
|
188
171
|
let routerContextVal;
|
|
189
172
|
try {
|
|
@@ -192,9 +175,8 @@ function createRemoteComponent(info) {
|
|
|
192
175
|
} catch {
|
|
193
176
|
enableDispathPopstate = false;
|
|
194
177
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
} else if (enableDispathPopstate) {
|
|
178
|
+
let basename = "/";
|
|
179
|
+
if (!props.basename && enableDispathPopstate) {
|
|
198
180
|
const ReactRouterDOMAny = ReactRouterDOM__namespace;
|
|
199
181
|
const useRouteMatch = ReactRouterDOMAny["useRouteMatch"];
|
|
200
182
|
const useHistory = ReactRouterDOMAny["useHistory"];
|
|
@@ -205,11 +187,10 @@ function createRemoteComponent(info) {
|
|
|
205
187
|
basename = useHref == null ? void 0 : useHref("/");
|
|
206
188
|
}
|
|
207
189
|
routerContextVal = React.useContext(UNSAFE_RouteContext);
|
|
208
|
-
if (routerContextVal && routerContextVal.matches && routerContextVal.matches
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
);
|
|
190
|
+
if (routerContextVal && routerContextVal.matches && routerContextVal.matches.length > 0) {
|
|
191
|
+
const matchIndex = routerContextVal.matches.length - 1;
|
|
192
|
+
const pathnameBase = routerContextVal.matches[matchIndex].pathnameBase;
|
|
193
|
+
basename = context.pathJoin(basename, pathnameBase || "/");
|
|
213
194
|
}
|
|
214
195
|
} else {
|
|
215
196
|
const match = useRouteMatch == null ? void 0 : useRouteMatch();
|
|
@@ -222,54 +203,80 @@ function createRemoteComponent(info) {
|
|
|
222
203
|
}
|
|
223
204
|
}
|
|
224
205
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
);
|
|
241
|
-
const exportFn = m2[exportName];
|
|
242
|
-
if (exportName in m2 && typeof exportFn === "function") {
|
|
243
|
-
return {
|
|
244
|
-
default: () => /* @__PURE__ */ React.createElement(
|
|
245
|
-
RemoteApp,
|
|
246
|
-
{
|
|
247
|
-
name: moduleName,
|
|
248
|
-
dispathPopstate: enableDispathPopstate,
|
|
249
|
-
...info,
|
|
250
|
-
...props,
|
|
251
|
-
providerInfo: exportFn,
|
|
252
|
-
basename
|
|
253
|
-
}
|
|
254
|
-
)
|
|
255
|
-
};
|
|
256
|
-
} else {
|
|
257
|
-
context.LoggerInstance.log(
|
|
258
|
-
`createRemoteComponent LazyComponent module not found >>>`,
|
|
259
|
-
{ basename, name: moduleName, module: m2, exportName, props }
|
|
260
|
-
);
|
|
261
|
-
throw Error(
|
|
262
|
-
`Make sure that ${moduleName} has the correct export when export is ${String(
|
|
263
|
-
exportName
|
|
264
|
-
)}`
|
|
265
|
-
);
|
|
266
|
-
}
|
|
267
|
-
} catch (error) {
|
|
268
|
-
throw error;
|
|
206
|
+
context.LoggerInstance.log(`createRemoteComponent withRouterData >>>`, {
|
|
207
|
+
...props,
|
|
208
|
+
basename,
|
|
209
|
+
routerContextVal,
|
|
210
|
+
enableDispathPopstate
|
|
211
|
+
});
|
|
212
|
+
if (enableDispathPopstate) {
|
|
213
|
+
const location = ReactRouterDOM__namespace.useLocation();
|
|
214
|
+
const [pathname, setPathname] = React.useState(location.pathname);
|
|
215
|
+
React.useEffect(() => {
|
|
216
|
+
if (pathname !== "" && pathname !== location.pathname) {
|
|
217
|
+
context.LoggerInstance.log(`createRemoteComponent dispatchPopstateEnv >>>`, {
|
|
218
|
+
name: props.name,
|
|
219
|
+
pathname: location.pathname
|
|
220
|
+
});
|
|
221
|
+
context.f();
|
|
269
222
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
223
|
+
setPathname(location.pathname);
|
|
224
|
+
}, [location]);
|
|
225
|
+
}
|
|
226
|
+
return /* @__PURE__ */ React.createElement(WrappedComponent, { ...props, basename });
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
const RemoteApp$1 = withRouterData(RemoteApp);
|
|
230
|
+
function createLazyRemoteComponent(info) {
|
|
231
|
+
const exportName = (info == null ? void 0 : info.export) || "default";
|
|
232
|
+
return React.lazy(async () => {
|
|
233
|
+
context.LoggerInstance.log(`createRemoteComponent LazyComponent create >>>`, {
|
|
234
|
+
lazyComponent: info.loader,
|
|
235
|
+
exportName
|
|
236
|
+
});
|
|
237
|
+
try {
|
|
238
|
+
const m2 = await info.loader();
|
|
239
|
+
const moduleName = m2 && m2[Symbol.for("mf_module_id")];
|
|
240
|
+
context.LoggerInstance.log(
|
|
241
|
+
`createRemoteComponent LazyComponent loadRemote info >>>`,
|
|
242
|
+
{ name: moduleName, module: m2, exportName }
|
|
243
|
+
);
|
|
244
|
+
const exportFn = m2[exportName];
|
|
245
|
+
if (exportName in m2 && typeof exportFn === "function") {
|
|
246
|
+
const RemoteAppComponent = React.forwardRef((props, _ref) => {
|
|
247
|
+
return /* @__PURE__ */ React.createElement(
|
|
248
|
+
RemoteApp$1,
|
|
249
|
+
{
|
|
250
|
+
name: moduleName,
|
|
251
|
+
providerInfo: exportFn,
|
|
252
|
+
exportName: info.export || "default",
|
|
253
|
+
...props
|
|
254
|
+
}
|
|
255
|
+
);
|
|
256
|
+
});
|
|
257
|
+
return {
|
|
258
|
+
default: RemoteAppComponent
|
|
259
|
+
};
|
|
260
|
+
} else {
|
|
261
|
+
context.LoggerInstance.log(
|
|
262
|
+
`createRemoteComponent LazyComponent module not found >>>`,
|
|
263
|
+
{ name: moduleName, module: m2, exportName }
|
|
264
|
+
);
|
|
265
|
+
throw Error(
|
|
266
|
+
`Make sure that ${moduleName} has the correct export when export is ${String(
|
|
267
|
+
exportName
|
|
268
|
+
)}`
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
} catch (error) {
|
|
272
|
+
throw error;
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
function createRemoteComponent(info) {
|
|
277
|
+
const LazyComponent = createLazyRemoteComponent(info);
|
|
278
|
+
return (props) => {
|
|
279
|
+
return /* @__PURE__ */ React.createElement(ErrorBoundary, { FallbackComponent: info.fallback }, /* @__PURE__ */ React.createElement(React.Suspense, { fallback: info.loading }, /* @__PURE__ */ React.createElement(LazyComponent, { ...props })));
|
|
273
280
|
};
|
|
274
281
|
}
|
|
275
282
|
var client = {};
|
package/dist/index.es.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import React__default, { createContext, Component, createElement, isValidElement, useContext,
|
|
3
|
-
import * as ReactRouterDOM from "react-router-dom";
|
|
2
|
+
import React__default, { createContext, Component, createElement, isValidElement, useContext, useState, useEffect, useRef, forwardRef } from "react";
|
|
4
3
|
import { p as pathJoin, L as LoggerInstance, f, a as atLeastReact18, R as RouterContext } from "./context-Bw2PEwa6.js";
|
|
4
|
+
import * as ReactRouterDOM from "react-router-dom";
|
|
5
5
|
import ReactDOM from "react-dom";
|
|
6
6
|
const ErrorBoundaryContext = createContext(null);
|
|
7
7
|
const initialState = {
|
|
@@ -103,26 +103,11 @@ const RemoteApp = ({
|
|
|
103
103
|
memoryRoute,
|
|
104
104
|
basename,
|
|
105
105
|
providerInfo,
|
|
106
|
-
dispathPopstate,
|
|
107
106
|
...resProps
|
|
108
107
|
}) => {
|
|
109
108
|
const rootRef = useRef(null);
|
|
110
109
|
const renderDom = useRef(null);
|
|
111
110
|
const providerInfoRef = useRef(null);
|
|
112
|
-
if (dispathPopstate) {
|
|
113
|
-
const location = ReactRouterDOM.useLocation();
|
|
114
|
-
const [pathname, setPathname] = useState(location.pathname);
|
|
115
|
-
useEffect(() => {
|
|
116
|
-
if (pathname !== "" && pathname !== location.pathname) {
|
|
117
|
-
LoggerInstance.log(`createRemoteComponent dispatchPopstateEnv >>>`, {
|
|
118
|
-
name,
|
|
119
|
-
pathname: location.pathname
|
|
120
|
-
});
|
|
121
|
-
f();
|
|
122
|
-
}
|
|
123
|
-
setPathname(location.pathname);
|
|
124
|
-
}, [location]);
|
|
125
|
-
}
|
|
126
111
|
useEffect(() => {
|
|
127
112
|
const renderTimeout = setTimeout(() => {
|
|
128
113
|
const providerReturn = providerInfo();
|
|
@@ -159,12 +144,10 @@ const RemoteApp = ({
|
|
|
159
144
|
}, []);
|
|
160
145
|
return /* @__PURE__ */ React__default.createElement("div", { ref: rootRef });
|
|
161
146
|
};
|
|
162
|
-
RemoteApp["__APP_VERSION__"] = "0.2.
|
|
163
|
-
function
|
|
147
|
+
RemoteApp["__APP_VERSION__"] = "0.2.6";
|
|
148
|
+
function withRouterData(WrappedComponent) {
|
|
164
149
|
return (props) => {
|
|
165
150
|
var _a;
|
|
166
|
-
const exportName = (info == null ? void 0 : info.export) || "default";
|
|
167
|
-
let basename = "/";
|
|
168
151
|
let enableDispathPopstate = false;
|
|
169
152
|
let routerContextVal;
|
|
170
153
|
try {
|
|
@@ -173,9 +156,8 @@ function createRemoteComponent(info) {
|
|
|
173
156
|
} catch {
|
|
174
157
|
enableDispathPopstate = false;
|
|
175
158
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
} else if (enableDispathPopstate) {
|
|
159
|
+
let basename = "/";
|
|
160
|
+
if (!props.basename && enableDispathPopstate) {
|
|
179
161
|
const ReactRouterDOMAny = ReactRouterDOM;
|
|
180
162
|
const useRouteMatch = ReactRouterDOMAny["useRouteMatch"];
|
|
181
163
|
const useHistory = ReactRouterDOMAny["useHistory"];
|
|
@@ -186,11 +168,10 @@ function createRemoteComponent(info) {
|
|
|
186
168
|
basename = useHref == null ? void 0 : useHref("/");
|
|
187
169
|
}
|
|
188
170
|
routerContextVal = useContext(UNSAFE_RouteContext);
|
|
189
|
-
if (routerContextVal && routerContextVal.matches && routerContextVal.matches
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
);
|
|
171
|
+
if (routerContextVal && routerContextVal.matches && routerContextVal.matches.length > 0) {
|
|
172
|
+
const matchIndex = routerContextVal.matches.length - 1;
|
|
173
|
+
const pathnameBase = routerContextVal.matches[matchIndex].pathnameBase;
|
|
174
|
+
basename = pathJoin(basename, pathnameBase || "/");
|
|
194
175
|
}
|
|
195
176
|
} else {
|
|
196
177
|
const match = useRouteMatch == null ? void 0 : useRouteMatch();
|
|
@@ -203,54 +184,80 @@ function createRemoteComponent(info) {
|
|
|
203
184
|
}
|
|
204
185
|
}
|
|
205
186
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
);
|
|
222
|
-
const exportFn = m2[exportName];
|
|
223
|
-
if (exportName in m2 && typeof exportFn === "function") {
|
|
224
|
-
return {
|
|
225
|
-
default: () => /* @__PURE__ */ React__default.createElement(
|
|
226
|
-
RemoteApp,
|
|
227
|
-
{
|
|
228
|
-
name: moduleName,
|
|
229
|
-
dispathPopstate: enableDispathPopstate,
|
|
230
|
-
...info,
|
|
231
|
-
...props,
|
|
232
|
-
providerInfo: exportFn,
|
|
233
|
-
basename
|
|
234
|
-
}
|
|
235
|
-
)
|
|
236
|
-
};
|
|
237
|
-
} else {
|
|
238
|
-
LoggerInstance.log(
|
|
239
|
-
`createRemoteComponent LazyComponent module not found >>>`,
|
|
240
|
-
{ basename, name: moduleName, module: m2, exportName, props }
|
|
241
|
-
);
|
|
242
|
-
throw Error(
|
|
243
|
-
`Make sure that ${moduleName} has the correct export when export is ${String(
|
|
244
|
-
exportName
|
|
245
|
-
)}`
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
} catch (error) {
|
|
249
|
-
throw error;
|
|
187
|
+
LoggerInstance.log(`createRemoteComponent withRouterData >>>`, {
|
|
188
|
+
...props,
|
|
189
|
+
basename,
|
|
190
|
+
routerContextVal,
|
|
191
|
+
enableDispathPopstate
|
|
192
|
+
});
|
|
193
|
+
if (enableDispathPopstate) {
|
|
194
|
+
const location = ReactRouterDOM.useLocation();
|
|
195
|
+
const [pathname, setPathname] = useState(location.pathname);
|
|
196
|
+
useEffect(() => {
|
|
197
|
+
if (pathname !== "" && pathname !== location.pathname) {
|
|
198
|
+
LoggerInstance.log(`createRemoteComponent dispatchPopstateEnv >>>`, {
|
|
199
|
+
name: props.name,
|
|
200
|
+
pathname: location.pathname
|
|
201
|
+
});
|
|
202
|
+
f();
|
|
250
203
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
204
|
+
setPathname(location.pathname);
|
|
205
|
+
}, [location]);
|
|
206
|
+
}
|
|
207
|
+
return /* @__PURE__ */ React__default.createElement(WrappedComponent, { ...props, basename });
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
const RemoteApp$1 = withRouterData(RemoteApp);
|
|
211
|
+
function createLazyRemoteComponent(info) {
|
|
212
|
+
const exportName = (info == null ? void 0 : info.export) || "default";
|
|
213
|
+
return React__default.lazy(async () => {
|
|
214
|
+
LoggerInstance.log(`createRemoteComponent LazyComponent create >>>`, {
|
|
215
|
+
lazyComponent: info.loader,
|
|
216
|
+
exportName
|
|
217
|
+
});
|
|
218
|
+
try {
|
|
219
|
+
const m2 = await info.loader();
|
|
220
|
+
const moduleName = m2 && m2[Symbol.for("mf_module_id")];
|
|
221
|
+
LoggerInstance.log(
|
|
222
|
+
`createRemoteComponent LazyComponent loadRemote info >>>`,
|
|
223
|
+
{ name: moduleName, module: m2, exportName }
|
|
224
|
+
);
|
|
225
|
+
const exportFn = m2[exportName];
|
|
226
|
+
if (exportName in m2 && typeof exportFn === "function") {
|
|
227
|
+
const RemoteAppComponent = forwardRef((props, _ref) => {
|
|
228
|
+
return /* @__PURE__ */ React__default.createElement(
|
|
229
|
+
RemoteApp$1,
|
|
230
|
+
{
|
|
231
|
+
name: moduleName,
|
|
232
|
+
providerInfo: exportFn,
|
|
233
|
+
exportName: info.export || "default",
|
|
234
|
+
...props
|
|
235
|
+
}
|
|
236
|
+
);
|
|
237
|
+
});
|
|
238
|
+
return {
|
|
239
|
+
default: RemoteAppComponent
|
|
240
|
+
};
|
|
241
|
+
} else {
|
|
242
|
+
LoggerInstance.log(
|
|
243
|
+
`createRemoteComponent LazyComponent module not found >>>`,
|
|
244
|
+
{ name: moduleName, module: m2, exportName }
|
|
245
|
+
);
|
|
246
|
+
throw Error(
|
|
247
|
+
`Make sure that ${moduleName} has the correct export when export is ${String(
|
|
248
|
+
exportName
|
|
249
|
+
)}`
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
} catch (error) {
|
|
253
|
+
throw error;
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
function createRemoteComponent(info) {
|
|
258
|
+
const LazyComponent = createLazyRemoteComponent(info);
|
|
259
|
+
return (props) => {
|
|
260
|
+
return /* @__PURE__ */ React__default.createElement(ErrorBoundary, { FallbackComponent: info.fallback }, /* @__PURE__ */ React__default.createElement(React__default.Suspense, { fallback: info.loading }, /* @__PURE__ */ React__default.createElement(LazyComponent, { ...props })));
|
|
254
261
|
};
|
|
255
262
|
}
|
|
256
263
|
var client = {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@module-federation/bridge-react",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@loadable/component": "^5.16.4",
|
|
27
27
|
"react-error-boundary": "^4.0.13",
|
|
28
|
-
"@module-federation/bridge-shared": "0.2.
|
|
28
|
+
"@module-federation/bridge-shared": "0.2.6"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"react": ">=16.9.0",
|
package/src/create.tsx
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import * as ReactRouterDOM from 'react-router-dom';
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
3
2
|
import type { ProviderParams } from '@module-federation/bridge-shared';
|
|
4
|
-
import { LoggerInstance
|
|
5
|
-
import { dispatchPopstateEnv } from '@module-federation/bridge-shared';
|
|
3
|
+
import { LoggerInstance } from './utils';
|
|
6
4
|
import {
|
|
7
5
|
ErrorBoundary,
|
|
8
6
|
ErrorBoundaryPropsWithComponent,
|
|
9
7
|
} from 'react-error-boundary';
|
|
10
|
-
|
|
11
|
-
declare const __APP_VERSION__: string;
|
|
8
|
+
import RemoteApp from './remote';
|
|
12
9
|
|
|
13
10
|
export interface RenderFnParams extends ProviderParams {
|
|
14
11
|
dom?: any;
|
|
@@ -25,79 +22,67 @@ interface RemoteModule {
|
|
|
25
22
|
};
|
|
26
23
|
}
|
|
27
24
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const providerInfoRef = useRef<any>(null);
|
|
45
|
-
if (dispathPopstate) {
|
|
46
|
-
const location = ReactRouterDOM.useLocation();
|
|
47
|
-
const [pathname, setPathname] = useState(location.pathname);
|
|
48
|
-
|
|
49
|
-
useEffect(() => {
|
|
50
|
-
if (pathname !== '' && pathname !== location.pathname) {
|
|
51
|
-
LoggerInstance.log(`createRemoteComponent dispatchPopstateEnv >>>`, {
|
|
52
|
-
name,
|
|
53
|
-
pathname: location.pathname,
|
|
54
|
-
});
|
|
55
|
-
dispatchPopstateEnv();
|
|
56
|
-
}
|
|
57
|
-
setPathname(location.pathname);
|
|
58
|
-
}, [location]);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
useEffect(() => {
|
|
62
|
-
const renderTimeout = setTimeout(() => {
|
|
63
|
-
const providerReturn = providerInfo();
|
|
64
|
-
providerInfoRef.current = providerReturn;
|
|
65
|
-
const renderProps = {
|
|
66
|
-
name,
|
|
67
|
-
dom: rootRef.current,
|
|
68
|
-
basename,
|
|
69
|
-
memoryRoute,
|
|
70
|
-
...resProps,
|
|
71
|
-
};
|
|
72
|
-
renderDom.current = rootRef.current;
|
|
25
|
+
function createLazyRemoteComponent<T, E extends keyof T>(info: {
|
|
26
|
+
loader: () => Promise<T>;
|
|
27
|
+
loading: React.ReactNode;
|
|
28
|
+
fallback: ErrorBoundaryPropsWithComponent['FallbackComponent'];
|
|
29
|
+
export?: E;
|
|
30
|
+
}) {
|
|
31
|
+
const exportName = info?.export || 'default';
|
|
32
|
+
return React.lazy(async () => {
|
|
33
|
+
LoggerInstance.log(`createRemoteComponent LazyComponent create >>>`, {
|
|
34
|
+
lazyComponent: info.loader,
|
|
35
|
+
exportName,
|
|
36
|
+
});
|
|
37
|
+
try {
|
|
38
|
+
const m = (await info.loader()) as RemoteModule;
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
const moduleName = m && m[Symbol.for('mf_module_id')];
|
|
73
41
|
LoggerInstance.log(
|
|
74
|
-
`createRemoteComponent LazyComponent
|
|
75
|
-
|
|
42
|
+
`createRemoteComponent LazyComponent loadRemote info >>>`,
|
|
43
|
+
{ name: moduleName, module: m, exportName },
|
|
76
44
|
);
|
|
77
|
-
providerReturn.render(renderProps);
|
|
78
|
-
});
|
|
79
45
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
setTimeout(() => {
|
|
83
|
-
if (providerInfoRef.current?.destroy) {
|
|
84
|
-
LoggerInstance.log(
|
|
85
|
-
`createRemoteComponent LazyComponent destroy >>>`,
|
|
86
|
-
{ name, basename, dom: renderDom.current },
|
|
87
|
-
);
|
|
88
|
-
providerInfoRef.current?.destroy({
|
|
89
|
-
dom: renderDom.current,
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
};
|
|
94
|
-
}, []);
|
|
46
|
+
// @ts-ignore
|
|
47
|
+
const exportFn = m[exportName] as any;
|
|
95
48
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
49
|
+
if (exportName in m && typeof exportFn === 'function') {
|
|
50
|
+
const RemoteAppComponent = forwardRef<
|
|
51
|
+
HTMLDivElement,
|
|
52
|
+
{
|
|
53
|
+
basename?: ProviderParams['basename'];
|
|
54
|
+
memoryRoute?: ProviderParams['memoryRoute'];
|
|
55
|
+
}
|
|
56
|
+
>((props, _ref) => {
|
|
57
|
+
return (
|
|
58
|
+
<RemoteApp
|
|
59
|
+
name={moduleName}
|
|
60
|
+
providerInfo={exportFn}
|
|
61
|
+
exportName={info.export || 'default'}
|
|
62
|
+
{...props}
|
|
63
|
+
/>
|
|
64
|
+
);
|
|
65
|
+
});
|
|
99
66
|
|
|
100
|
-
|
|
67
|
+
return {
|
|
68
|
+
default: RemoteAppComponent,
|
|
69
|
+
};
|
|
70
|
+
} else {
|
|
71
|
+
LoggerInstance.log(
|
|
72
|
+
`createRemoteComponent LazyComponent module not found >>>`,
|
|
73
|
+
{ name: moduleName, module: m, exportName },
|
|
74
|
+
);
|
|
75
|
+
throw Error(
|
|
76
|
+
`Make sure that ${moduleName} has the correct export when export is ${String(
|
|
77
|
+
exportName,
|
|
78
|
+
)}`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
} catch (error) {
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
101
86
|
|
|
102
87
|
export function createRemoteComponent<T, E extends keyof T>(info: {
|
|
103
88
|
loader: () => Promise<T>;
|
|
@@ -114,121 +99,18 @@ export function createRemoteComponent<T, E extends keyof T>(info: {
|
|
|
114
99
|
: {}
|
|
115
100
|
: {};
|
|
116
101
|
|
|
102
|
+
const LazyComponent = createLazyRemoteComponent(info);
|
|
103
|
+
|
|
117
104
|
return (
|
|
118
105
|
props: {
|
|
119
106
|
basename?: ProviderParams['basename'];
|
|
120
107
|
memoryRoute?: ProviderParams['memoryRoute'];
|
|
121
108
|
} & RawComponentType,
|
|
122
109
|
) => {
|
|
123
|
-
const exportName = info?.export || 'default';
|
|
124
|
-
let basename = '/';
|
|
125
|
-
let enableDispathPopstate = false;
|
|
126
|
-
let routerContextVal: any;
|
|
127
|
-
try {
|
|
128
|
-
ReactRouterDOM.useLocation();
|
|
129
|
-
enableDispathPopstate = true;
|
|
130
|
-
} catch {
|
|
131
|
-
enableDispathPopstate = false;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (props.basename) {
|
|
135
|
-
basename = props.basename;
|
|
136
|
-
} else if (enableDispathPopstate) {
|
|
137
|
-
const ReactRouterDOMAny: any = ReactRouterDOM;
|
|
138
|
-
// Avoid building tools checking references
|
|
139
|
-
const useRouteMatch = ReactRouterDOMAny['use' + 'RouteMatch']; //v5
|
|
140
|
-
const useHistory = ReactRouterDOMAny['use' + 'History']; //v5
|
|
141
|
-
const useHref = ReactRouterDOMAny['use' + 'Href'];
|
|
142
|
-
const UNSAFE_RouteContext = ReactRouterDOMAny['UNSAFE_' + 'RouteContext'];
|
|
143
|
-
|
|
144
|
-
if (UNSAFE_RouteContext /* react-router@6 */) {
|
|
145
|
-
if (useHref) {
|
|
146
|
-
basename = useHref?.('/');
|
|
147
|
-
}
|
|
148
|
-
routerContextVal = useContext(UNSAFE_RouteContext);
|
|
149
|
-
if (
|
|
150
|
-
routerContextVal &&
|
|
151
|
-
routerContextVal.matches &&
|
|
152
|
-
routerContextVal.matches[0] &&
|
|
153
|
-
routerContextVal.matches[0].pathnameBase
|
|
154
|
-
) {
|
|
155
|
-
basename = pathJoin(
|
|
156
|
-
basename,
|
|
157
|
-
routerContextVal.matches[0].pathnameBase || '/',
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
} /* react-router@5 */ else {
|
|
161
|
-
const match = useRouteMatch?.(); // v5
|
|
162
|
-
if (useHistory /* react-router@5 */) {
|
|
163
|
-
// there is no dynamic switching of the router version in the project
|
|
164
|
-
// so hooks can be used in conditional judgment
|
|
165
|
-
const history = useHistory?.();
|
|
166
|
-
// To be compatible to history@4.10.1 and @5.3.0 we cannot write like this `history.createHref(pathname)`
|
|
167
|
-
basename = history?.createHref?.({ pathname: '/' });
|
|
168
|
-
}
|
|
169
|
-
if (match /* react-router@5 */) {
|
|
170
|
-
basename = pathJoin(basename, match?.path || '/');
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const LazyComponent = useMemo(() => {
|
|
176
|
-
//@ts-ignore
|
|
177
|
-
return React.lazy(async () => {
|
|
178
|
-
LoggerInstance.log(`createRemoteComponent LazyComponent create >>>`, {
|
|
179
|
-
basename,
|
|
180
|
-
lazyComponent: info.loader,
|
|
181
|
-
exportName,
|
|
182
|
-
props,
|
|
183
|
-
routerContextVal,
|
|
184
|
-
});
|
|
185
|
-
try {
|
|
186
|
-
const m = (await info.loader()) as RemoteModule;
|
|
187
|
-
// @ts-ignore
|
|
188
|
-
const moduleName = m && m[Symbol.for('mf_module_id')];
|
|
189
|
-
LoggerInstance.log(
|
|
190
|
-
`createRemoteComponent LazyComponent loadRemote info >>>`,
|
|
191
|
-
{ basename, name: moduleName, module: m, exportName, props },
|
|
192
|
-
);
|
|
193
|
-
|
|
194
|
-
// @ts-ignore
|
|
195
|
-
const exportFn = m[exportName] as any;
|
|
196
|
-
|
|
197
|
-
if (exportName in m && typeof exportFn === 'function') {
|
|
198
|
-
return {
|
|
199
|
-
default: () => (
|
|
200
|
-
<RemoteApp
|
|
201
|
-
name={moduleName}
|
|
202
|
-
dispathPopstate={enableDispathPopstate}
|
|
203
|
-
{...info}
|
|
204
|
-
{...props}
|
|
205
|
-
providerInfo={exportFn}
|
|
206
|
-
basename={basename}
|
|
207
|
-
/>
|
|
208
|
-
),
|
|
209
|
-
};
|
|
210
|
-
} else {
|
|
211
|
-
LoggerInstance.log(
|
|
212
|
-
`createRemoteComponent LazyComponent module not found >>>`,
|
|
213
|
-
{ basename, name: moduleName, module: m, exportName, props },
|
|
214
|
-
);
|
|
215
|
-
throw Error(
|
|
216
|
-
`Make sure that ${moduleName} has the correct export when export is ${String(
|
|
217
|
-
exportName,
|
|
218
|
-
)}`,
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
} catch (error) {
|
|
222
|
-
throw error;
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
}, [exportName, basename, props.memoryRoute]);
|
|
226
|
-
|
|
227
|
-
//@ts-ignore
|
|
228
110
|
return (
|
|
229
111
|
<ErrorBoundary FallbackComponent={info.fallback}>
|
|
230
112
|
<React.Suspense fallback={info.loading}>
|
|
231
|
-
<LazyComponent />
|
|
113
|
+
<LazyComponent {...props} />
|
|
232
114
|
</React.Suspense>
|
|
233
115
|
</ErrorBoundary>
|
|
234
116
|
);
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import React, { useContext, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import * as ReactRouterDOM from 'react-router-dom';
|
|
3
|
+
import type { ProviderParams } from '@module-federation/bridge-shared';
|
|
4
|
+
import { LoggerInstance, pathJoin } from '../utils';
|
|
5
|
+
import { dispatchPopstateEnv } from '@module-federation/bridge-shared';
|
|
6
|
+
|
|
7
|
+
declare const __APP_VERSION__: string;
|
|
8
|
+
|
|
9
|
+
export interface RenderFnParams extends ProviderParams {
|
|
10
|
+
dom?: any;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface RemoteModule {
|
|
14
|
+
provider: () => {
|
|
15
|
+
render: (
|
|
16
|
+
info: ProviderParams & {
|
|
17
|
+
dom: any;
|
|
18
|
+
},
|
|
19
|
+
) => void;
|
|
20
|
+
destroy: (info: { dom: any }) => void;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface RemoteAppParams {
|
|
25
|
+
name: string;
|
|
26
|
+
providerInfo: NonNullable<RemoteModule['provider']>;
|
|
27
|
+
exportName: string | number | symbol;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const RemoteApp = ({
|
|
31
|
+
name,
|
|
32
|
+
memoryRoute,
|
|
33
|
+
basename,
|
|
34
|
+
providerInfo,
|
|
35
|
+
...resProps
|
|
36
|
+
}: RemoteAppParams & ProviderParams) => {
|
|
37
|
+
const rootRef = useRef(null);
|
|
38
|
+
const renderDom = useRef(null);
|
|
39
|
+
const providerInfoRef = useRef<any>(null);
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const renderTimeout = setTimeout(() => {
|
|
43
|
+
const providerReturn = providerInfo();
|
|
44
|
+
providerInfoRef.current = providerReturn;
|
|
45
|
+
const renderProps = {
|
|
46
|
+
name,
|
|
47
|
+
dom: rootRef.current,
|
|
48
|
+
basename,
|
|
49
|
+
memoryRoute,
|
|
50
|
+
...resProps,
|
|
51
|
+
};
|
|
52
|
+
renderDom.current = rootRef.current;
|
|
53
|
+
LoggerInstance.log(
|
|
54
|
+
`createRemoteComponent LazyComponent render >>>`,
|
|
55
|
+
renderProps,
|
|
56
|
+
);
|
|
57
|
+
providerReturn.render(renderProps);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return () => {
|
|
61
|
+
clearTimeout(renderTimeout);
|
|
62
|
+
setTimeout(() => {
|
|
63
|
+
if (providerInfoRef.current?.destroy) {
|
|
64
|
+
LoggerInstance.log(
|
|
65
|
+
`createRemoteComponent LazyComponent destroy >>>`,
|
|
66
|
+
{ name, basename, dom: renderDom.current },
|
|
67
|
+
);
|
|
68
|
+
providerInfoRef.current?.destroy({
|
|
69
|
+
dom: renderDom.current,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
}, []);
|
|
75
|
+
|
|
76
|
+
//@ts-ignore
|
|
77
|
+
return <div ref={rootRef}></div>;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
(RemoteApp as any)['__APP_VERSION__'] = __APP_VERSION__;
|
|
81
|
+
|
|
82
|
+
interface ExtraDataProps {
|
|
83
|
+
basename?: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function withRouterData<P extends Parameters<typeof RemoteApp>[0]>(
|
|
87
|
+
WrappedComponent: React.ComponentType<P & ExtraDataProps>,
|
|
88
|
+
): React.FC<Omit<P, keyof ExtraDataProps>> {
|
|
89
|
+
return (props: any) => {
|
|
90
|
+
let enableDispathPopstate = false;
|
|
91
|
+
let routerContextVal: any;
|
|
92
|
+
try {
|
|
93
|
+
ReactRouterDOM.useLocation();
|
|
94
|
+
enableDispathPopstate = true;
|
|
95
|
+
} catch {
|
|
96
|
+
enableDispathPopstate = false;
|
|
97
|
+
}
|
|
98
|
+
let basename = '/';
|
|
99
|
+
|
|
100
|
+
if (!props.basename && enableDispathPopstate) {
|
|
101
|
+
const ReactRouterDOMAny: any = ReactRouterDOM;
|
|
102
|
+
// Avoid building tools checking references
|
|
103
|
+
const useRouteMatch = ReactRouterDOMAny['use' + 'RouteMatch']; //v5
|
|
104
|
+
const useHistory = ReactRouterDOMAny['use' + 'History']; //v5
|
|
105
|
+
const useHref = ReactRouterDOMAny['use' + 'Href'];
|
|
106
|
+
const UNSAFE_RouteContext = ReactRouterDOMAny['UNSAFE_' + 'RouteContext'];
|
|
107
|
+
|
|
108
|
+
if (UNSAFE_RouteContext /* react-router@6 */) {
|
|
109
|
+
if (useHref) {
|
|
110
|
+
basename = useHref?.('/');
|
|
111
|
+
}
|
|
112
|
+
routerContextVal = useContext(UNSAFE_RouteContext);
|
|
113
|
+
if (
|
|
114
|
+
routerContextVal &&
|
|
115
|
+
routerContextVal.matches &&
|
|
116
|
+
routerContextVal.matches.length > 0
|
|
117
|
+
) {
|
|
118
|
+
const matchIndex = routerContextVal.matches.length - 1;
|
|
119
|
+
const pathnameBase =
|
|
120
|
+
routerContextVal.matches[matchIndex].pathnameBase;
|
|
121
|
+
basename = pathJoin(basename, pathnameBase || '/');
|
|
122
|
+
}
|
|
123
|
+
} /* react-router@5 */ else {
|
|
124
|
+
const match = useRouteMatch?.(); // v5
|
|
125
|
+
if (useHistory /* react-router@5 */) {
|
|
126
|
+
// there is no dynamic switching of the router version in the project
|
|
127
|
+
// so hooks can be used in conditional judgment
|
|
128
|
+
const history = useHistory?.();
|
|
129
|
+
// To be compatible to history@4.10.1 and @5.3.0 we cannot write like this `history.createHref(pathname)`
|
|
130
|
+
basename = history?.createHref?.({ pathname: '/' });
|
|
131
|
+
}
|
|
132
|
+
if (match /* react-router@5 */) {
|
|
133
|
+
basename = pathJoin(basename, match?.path || '/');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
LoggerInstance.log(`createRemoteComponent withRouterData >>>`, {
|
|
139
|
+
...props,
|
|
140
|
+
basename,
|
|
141
|
+
routerContextVal,
|
|
142
|
+
enableDispathPopstate,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
if (enableDispathPopstate) {
|
|
146
|
+
const location = ReactRouterDOM.useLocation();
|
|
147
|
+
const [pathname, setPathname] = useState(location.pathname);
|
|
148
|
+
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
if (pathname !== '' && pathname !== location.pathname) {
|
|
151
|
+
LoggerInstance.log(`createRemoteComponent dispatchPopstateEnv >>>`, {
|
|
152
|
+
name: props.name,
|
|
153
|
+
pathname: location.pathname,
|
|
154
|
+
});
|
|
155
|
+
dispatchPopstateEnv();
|
|
156
|
+
}
|
|
157
|
+
setPathname(location.pathname);
|
|
158
|
+
}, [location]);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return <WrappedComponent {...(props as P)} basename={basename} />;
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export default withRouterData(RemoteApp);
|