@module-federation/bridge-react 0.0.0-next-20240619092013

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.
@@ -0,0 +1,175 @@
1
+ import React, { useContext, useMemo, useRef, useState, useEffect } from "react";
2
+ import { UNSAFE_RouteContext, useLocation } from "react-router-dom";
3
+ import { L as LoggerInstance, f, R as RouterContext } from "./context-CoFgcMIF.js";
4
+ import require$$0 from "react-dom";
5
+ const RemoteApp = ({
6
+ name,
7
+ memoryRoute,
8
+ basename,
9
+ providerInfo,
10
+ ...resProps
11
+ }) => {
12
+ const rootRef = useRef(null);
13
+ const renderDom = useRef(null);
14
+ const location = useLocation();
15
+ const [pathname, setPathname] = useState(location.pathname);
16
+ const providerInfoRef = useRef(null);
17
+ useEffect(() => {
18
+ if (pathname !== "" && pathname !== location.pathname) {
19
+ LoggerInstance.log(`createRemoteComponent dispatchPopstateEnv >>>`, {
20
+ name,
21
+ pathname: location.pathname
22
+ });
23
+ f();
24
+ }
25
+ setPathname(location.pathname);
26
+ }, [location]);
27
+ useEffect(() => {
28
+ const renderTimeout = setTimeout(() => {
29
+ const providerReturn = providerInfo();
30
+ providerInfoRef.current = providerReturn;
31
+ const renderProps = {
32
+ name,
33
+ dom: rootRef.current,
34
+ basename,
35
+ memoryRoute,
36
+ ...resProps
37
+ };
38
+ renderDom.current = rootRef.current;
39
+ LoggerInstance.log(
40
+ `createRemoteComponent LazyComponent render >>>`,
41
+ renderProps
42
+ );
43
+ providerReturn.render(renderProps);
44
+ });
45
+ return () => {
46
+ clearTimeout(renderTimeout);
47
+ setTimeout(() => {
48
+ var _a, _b;
49
+ if ((_a = providerInfoRef.current) == null ? void 0 : _a.destroy) {
50
+ LoggerInstance.log(
51
+ `createRemoteComponent LazyComponent destroy >>>`,
52
+ { name, basename, dom: renderDom.current }
53
+ );
54
+ (_b = providerInfoRef.current) == null ? void 0 : _b.destroy({
55
+ dom: renderDom.current
56
+ });
57
+ }
58
+ });
59
+ };
60
+ }, []);
61
+ return /* @__PURE__ */ React.createElement("div", { ref: rootRef });
62
+ };
63
+ RemoteApp["__APP_VERSION__"] = "0.0.1";
64
+ function createRemoteComponent(lazyComponent, info) {
65
+ return (props) => {
66
+ const exportName = (info == null ? void 0 : info.export) || "default";
67
+ const routerContextVal = useContext(UNSAFE_RouteContext);
68
+ let basename = "/";
69
+ if (routerContextVal.matches[0] && routerContextVal.matches[0].pathnameBase) {
70
+ basename = routerContextVal.matches[0].pathnameBase;
71
+ }
72
+ const LazyComponent = useMemo(() => {
73
+ return React.lazy(async () => {
74
+ LoggerInstance.log(`createRemoteComponent LazyComponent create >>>`, {
75
+ basename,
76
+ lazyComponent,
77
+ exportName,
78
+ props
79
+ });
80
+ const m2 = await lazyComponent();
81
+ const moduleName = m2 && m2[Symbol.for("mf_module_id")];
82
+ LoggerInstance.log(
83
+ `createRemoteComponent LazyComponent loadRemote info >>>`,
84
+ { basename, name: moduleName, module: m2, exportName, props }
85
+ );
86
+ const exportFn = m2[exportName];
87
+ if (exportName in m2 && typeof exportFn === "function") {
88
+ return {
89
+ default: () => /* @__PURE__ */ React.createElement(
90
+ RemoteApp,
91
+ {
92
+ name: moduleName,
93
+ ...info,
94
+ ...props,
95
+ providerInfo: exportFn,
96
+ basename
97
+ }
98
+ )
99
+ };
100
+ }
101
+ throw Error("module not found");
102
+ });
103
+ }, [exportName, basename, props.memoryRoute]);
104
+ return /* @__PURE__ */ React.createElement(React.Suspense, { fallback: props.fallback }, /* @__PURE__ */ React.createElement(LazyComponent, null));
105
+ };
106
+ }
107
+ var client = {};
108
+ var m = require$$0;
109
+ if (process.env.NODE_ENV === "production") {
110
+ client.createRoot = m.createRoot;
111
+ client.hydrateRoot = m.hydrateRoot;
112
+ } else {
113
+ var i = m.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
114
+ client.createRoot = function(c, o) {
115
+ i.usingClientEntryPoint = true;
116
+ try {
117
+ return m.createRoot(c, o);
118
+ } finally {
119
+ i.usingClientEntryPoint = false;
120
+ }
121
+ };
122
+ client.hydrateRoot = function(c, h, o) {
123
+ i.usingClientEntryPoint = true;
124
+ try {
125
+ return m.hydrateRoot(c, h, o);
126
+ } finally {
127
+ i.usingClientEntryPoint = false;
128
+ }
129
+ };
130
+ }
131
+ function createBridgeComponent(bridgeInfo) {
132
+ return () => {
133
+ const rootMap = /* @__PURE__ */ new Map();
134
+ const RawComponent = (info) => {
135
+ const { appInfo, propsInfo } = info;
136
+ const { name, memoryRoute, basename = "/" } = appInfo;
137
+ return /* @__PURE__ */ React.createElement(RouterContext.Provider, { value: { name, basename, memoryRoute } }, /* @__PURE__ */ React.createElement(bridgeInfo.rootComponent, { ...propsInfo, basename }));
138
+ };
139
+ return {
140
+ render(info) {
141
+ LoggerInstance.log(`createBridgeComponent render Info`, info);
142
+ const root = client.createRoot(info.dom);
143
+ rootMap.set(info.dom, root);
144
+ const { name, basename, memoryRoute, ...propsInfo } = info;
145
+ root.render(
146
+ /* @__PURE__ */ React.createElement(
147
+ RawComponent,
148
+ {
149
+ propsInfo,
150
+ appInfo: {
151
+ name,
152
+ basename,
153
+ memoryRoute
154
+ }
155
+ }
156
+ )
157
+ );
158
+ },
159
+ destroy(info) {
160
+ LoggerInstance.log(`createBridgeComponent destroy Info`, {
161
+ dom: info.dom
162
+ });
163
+ const root = rootMap.get(info.dom);
164
+ root == null ? void 0 : root.unmount();
165
+ },
166
+ rawComponent: bridgeInfo.rootComponent,
167
+ __BRIDGE_FN__: (_args) => {
168
+ }
169
+ };
170
+ };
171
+ }
172
+ export {
173
+ createBridgeComponent,
174
+ createRemoteComponent
175
+ };
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const React = require("react");
4
+ const ReactRouterDom = require("react-router-dom/");
5
+ const context = require("./context-C7FfFcIe.cjs");
6
+ function _interopNamespaceDefault(e) {
7
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
8
+ if (e) {
9
+ for (const k in e) {
10
+ if (k !== "default") {
11
+ const d = Object.getOwnPropertyDescriptor(e, k);
12
+ Object.defineProperty(n, k, d.get ? d : {
13
+ enumerable: true,
14
+ get: () => e[k]
15
+ });
16
+ }
17
+ }
18
+ }
19
+ n.default = e;
20
+ return Object.freeze(n);
21
+ }
22
+ const ReactRouterDom__namespace = /* @__PURE__ */ _interopNamespaceDefault(ReactRouterDom);
23
+ function WraperRouter(props) {
24
+ const { basename, ...propsRes } = props;
25
+ const routerContextProps = React.useContext(context.RouterContext) || {};
26
+ context.LoggerInstance.log(`WraperRouter info >>>`, {
27
+ ...routerContextProps,
28
+ routerContextProps,
29
+ WraperRouterProps: props
30
+ });
31
+ if (!routerContextProps)
32
+ return /* @__PURE__ */ React.createElement(ReactRouterDom__namespace.BrowserRouter, { ...props });
33
+ if (routerContextProps == null ? void 0 : routerContextProps.memoryRoute) {
34
+ return /* @__PURE__ */ React.createElement(
35
+ ReactRouterDom__namespace.MemoryRouter,
36
+ {
37
+ ...props,
38
+ initialEntries: [routerContextProps == null ? void 0 : routerContextProps.memoryRoute.entryPath]
39
+ }
40
+ );
41
+ }
42
+ return /* @__PURE__ */ React.createElement(
43
+ ReactRouterDom__namespace.BrowserRouter,
44
+ {
45
+ ...propsRes,
46
+ basename: (routerContextProps == null ? void 0 : routerContextProps.basename) || basename
47
+ }
48
+ );
49
+ }
50
+ function WraperRouterProvider(props) {
51
+ const { router, ...propsRes } = props;
52
+ const routerContextProps = React.useContext(context.RouterContext) || {};
53
+ const routers = router.routes;
54
+ context.LoggerInstance.log(`WraperRouterProvider info >>>`, {
55
+ ...routerContextProps,
56
+ routerContextProps,
57
+ WraperRouterProviderProps: props,
58
+ router
59
+ });
60
+ if (!routerContextProps)
61
+ return /* @__PURE__ */ React.createElement(ReactRouterDom__namespace.RouterProvider, { ...props });
62
+ if (routerContextProps.memoryRoute) {
63
+ const MemeoryRouterInstance = ReactRouterDom__namespace.createMemoryRouter(routers, {
64
+ initialEntries: [routerContextProps == null ? void 0 : routerContextProps.memoryRoute.entryPath]
65
+ });
66
+ return /* @__PURE__ */ React.createElement(ReactRouterDom__namespace.RouterProvider, { router: MemeoryRouterInstance });
67
+ } else {
68
+ const BrowserRouterInstance = ReactRouterDom__namespace.createBrowserRouter(routers, {
69
+ basename: routerContextProps.basename,
70
+ future: router.future,
71
+ window: router.window
72
+ });
73
+ return /* @__PURE__ */ React.createElement(
74
+ ReactRouterDom__namespace.RouterProvider,
75
+ {
76
+ ...propsRes,
77
+ router: BrowserRouterInstance
78
+ }
79
+ );
80
+ }
81
+ }
82
+ exports.BrowserRouter = WraperRouter;
83
+ exports.RouterProvider = WraperRouterProvider;
84
+ Object.keys(ReactRouterDom).forEach((k) => {
85
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k))
86
+ Object.defineProperty(exports, k, {
87
+ enumerable: true,
88
+ get: () => ReactRouterDom[k]
89
+ });
90
+ });
@@ -0,0 +1,11 @@
1
+ import { default as default_2 } from 'react';
2
+ import * as ReactRouterDom from 'react-router-dom/';
3
+
4
+ export declare function BrowserRouter(props: Parameters<typeof ReactRouterDom.BrowserRouter>[0] | Parameters<typeof ReactRouterDom.MemoryRouter>[0]): default_2.JSX.Element;
5
+
6
+ export declare function RouterProvider(props: Parameters<typeof ReactRouterDom.RouterProvider>[0]): default_2.JSX.Element;
7
+
8
+
9
+ export * from "react-router-dom/";
10
+
11
+ export { }
@@ -0,0 +1,67 @@
1
+ import React, { useContext } from "react";
2
+ import * as ReactRouterDom from "react-router-dom/";
3
+ export * from "react-router-dom/";
4
+ import { R as RouterContext, L as LoggerInstance } from "./context-CoFgcMIF.js";
5
+ function WraperRouter(props) {
6
+ const { basename, ...propsRes } = props;
7
+ const routerContextProps = useContext(RouterContext) || {};
8
+ LoggerInstance.log(`WraperRouter info >>>`, {
9
+ ...routerContextProps,
10
+ routerContextProps,
11
+ WraperRouterProps: props
12
+ });
13
+ if (!routerContextProps)
14
+ return /* @__PURE__ */ React.createElement(ReactRouterDom.BrowserRouter, { ...props });
15
+ if (routerContextProps == null ? void 0 : routerContextProps.memoryRoute) {
16
+ return /* @__PURE__ */ React.createElement(
17
+ ReactRouterDom.MemoryRouter,
18
+ {
19
+ ...props,
20
+ initialEntries: [routerContextProps == null ? void 0 : routerContextProps.memoryRoute.entryPath]
21
+ }
22
+ );
23
+ }
24
+ return /* @__PURE__ */ React.createElement(
25
+ ReactRouterDom.BrowserRouter,
26
+ {
27
+ ...propsRes,
28
+ basename: (routerContextProps == null ? void 0 : routerContextProps.basename) || basename
29
+ }
30
+ );
31
+ }
32
+ function WraperRouterProvider(props) {
33
+ const { router, ...propsRes } = props;
34
+ const routerContextProps = useContext(RouterContext) || {};
35
+ const routers = router.routes;
36
+ LoggerInstance.log(`WraperRouterProvider info >>>`, {
37
+ ...routerContextProps,
38
+ routerContextProps,
39
+ WraperRouterProviderProps: props,
40
+ router
41
+ });
42
+ if (!routerContextProps)
43
+ return /* @__PURE__ */ React.createElement(ReactRouterDom.RouterProvider, { ...props });
44
+ if (routerContextProps.memoryRoute) {
45
+ const MemeoryRouterInstance = ReactRouterDom.createMemoryRouter(routers, {
46
+ initialEntries: [routerContextProps == null ? void 0 : routerContextProps.memoryRoute.entryPath]
47
+ });
48
+ return /* @__PURE__ */ React.createElement(ReactRouterDom.RouterProvider, { router: MemeoryRouterInstance });
49
+ } else {
50
+ const BrowserRouterInstance = ReactRouterDom.createBrowserRouter(routers, {
51
+ basename: routerContextProps.basename,
52
+ future: router.future,
53
+ window: router.window
54
+ });
55
+ return /* @__PURE__ */ React.createElement(
56
+ ReactRouterDom.RouterProvider,
57
+ {
58
+ ...propsRes,
59
+ router: BrowserRouterInstance
60
+ }
61
+ );
62
+ }
63
+ }
64
+ export {
65
+ WraperRouter as BrowserRouter,
66
+ WraperRouterProvider as RouterProvider
67
+ };
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@module-federation/bridge-react",
3
+ "version": "0.0.0-next-20240619092013",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "author": "zhouxiao <codingzx@gmail.com>",
8
+ "type": "module",
9
+ "main": "./dist/index.cjs.js",
10
+ "module": "./dist/index.es.js",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.es.js",
16
+ "require": "./dist/index.cjs.js"
17
+ },
18
+ "./router": {
19
+ "types": "./dist/router.d.ts",
20
+ "import": "./dist/router.es.js",
21
+ "require": "./dist/router.cjs.js"
22
+ },
23
+ "./*": "./*"
24
+ },
25
+ "dependencies": {
26
+ "@loadable/component": "^5.16.4",
27
+ "react-error-boundary": "^4.0.13",
28
+ "@module-federation/bridge-shared": "0.0.0-next-20240619092013"
29
+ },
30
+ "peerDependencies": {
31
+ "react": "=18",
32
+ "react-dom": "=18",
33
+ "react-router-dom": ">=5"
34
+ },
35
+ "devDependencies": {
36
+ "@testing-library/react": "15.0.7",
37
+ "@types/react": "18.2.79",
38
+ "@types/react-dom": "18.2.25",
39
+ "@vitejs/plugin-react": "^4.3.0",
40
+ "@vitejs/plugin-vue": "^5.0.4",
41
+ "@vitejs/plugin-vue-jsx": "^4.0.0",
42
+ "jsdom": "^24.1.0",
43
+ "react": "18.1.0",
44
+ "react-dom": "18.1.0",
45
+ "react-router-dom": "6.22.3",
46
+ "typescript": "^5.2.2",
47
+ "vite": "^5.2.0",
48
+ "vite-plugin-dts": "^3.9.1"
49
+ },
50
+ "scripts": {
51
+ "dev": "vite",
52
+ "build": "vite build",
53
+ "preview": "vite preview"
54
+ }
55
+ }
package/project.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "bridge-react",
3
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
+ "sourceRoot": "packages/bridge/bridge-react/src",
5
+ "projectType": "library",
6
+ "targets": {
7
+ "build": {
8
+ "executor": "nx:run-commands",
9
+ "options": {
10
+ "commands": ["npm run build --prefix packages/bridge/bridge-react"]
11
+ }
12
+ },
13
+ "test": {
14
+ "executor": "nx:run-commands",
15
+ "options": {
16
+ "parallel": false,
17
+ "commands": [
18
+ {
19
+ "command": "vitest run -c packages/bridge/bridge-react/vitest.config.ts",
20
+ "forwardAllArgs": false
21
+ }
22
+ ]
23
+ }
24
+ }
25
+ },
26
+ "tags": ["type:pkg"]
27
+ }
@@ -0,0 +1,9 @@
1
+ // eslint-disable-next-line import/no-commonjs
2
+ module.exports = {
3
+ root: true,
4
+ extends: ['@modern-js-app'],
5
+ parserOptions: {
6
+ tsconfigRootDir: __dirname,
7
+ project: ['../tsconfig.json'],
8
+ },
9
+ };
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { ProviderParams } from '@module-federation/bridge-shared';
3
+
4
+ export const RouterContext = React.createContext<ProviderParams | null>(null);
package/src/create.tsx ADDED
@@ -0,0 +1,178 @@
1
+ import React, {
2
+ ReactNode,
3
+ useContext,
4
+ useEffect,
5
+ useMemo,
6
+ useRef,
7
+ useState,
8
+ } from 'react';
9
+ import { UNSAFE_RouteContext, useLocation } from 'react-router-dom';
10
+ import type { ProviderParams } from '@module-federation/bridge-shared';
11
+ import { LoggerInstance } from './utils';
12
+ import { dispatchPopstateEnv } from '@module-federation/bridge-shared';
13
+
14
+ declare const __APP_VERSION__: string;
15
+
16
+ export interface RenderFnParams extends ProviderParams {
17
+ dom?: any;
18
+ }
19
+
20
+ interface RemoteModule {
21
+ provider: () => {
22
+ render: (
23
+ info: ProviderParams & {
24
+ dom: any;
25
+ },
26
+ ) => void;
27
+ destroy: (info: { dom: any }) => void;
28
+ };
29
+ }
30
+
31
+ interface RemoteAppParams {
32
+ name: string;
33
+ providerInfo: NonNullable<RemoteModule['provider']>;
34
+ }
35
+
36
+ const RemoteApp = ({
37
+ name,
38
+ memoryRoute,
39
+ basename,
40
+ providerInfo,
41
+ ...resProps
42
+ }: RemoteAppParams & ProviderParams) => {
43
+ const rootRef = useRef(null);
44
+ const renderDom = useRef(null);
45
+ const location = useLocation();
46
+ const [pathname, setPathname] = useState(location.pathname);
47
+ const providerInfoRef = useRef<any>(null);
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
+ useEffect(() => {
61
+ const renderTimeout = setTimeout(() => {
62
+ const providerReturn = providerInfo();
63
+ providerInfoRef.current = providerReturn;
64
+ const renderProps = {
65
+ name,
66
+ dom: rootRef.current,
67
+ basename,
68
+ memoryRoute,
69
+ ...resProps,
70
+ };
71
+ renderDom.current = rootRef.current;
72
+ LoggerInstance.log(
73
+ `createRemoteComponent LazyComponent render >>>`,
74
+ renderProps,
75
+ );
76
+ providerReturn.render(renderProps);
77
+ });
78
+
79
+ return () => {
80
+ clearTimeout(renderTimeout);
81
+ setTimeout(() => {
82
+ if (providerInfoRef.current?.destroy) {
83
+ LoggerInstance.log(
84
+ `createRemoteComponent LazyComponent destroy >>>`,
85
+ { name, basename, dom: renderDom.current },
86
+ );
87
+ providerInfoRef.current?.destroy({
88
+ dom: renderDom.current,
89
+ });
90
+ }
91
+ });
92
+ };
93
+ }, []);
94
+
95
+ //@ts-ignore
96
+ return <div ref={rootRef}></div>;
97
+ };
98
+
99
+ (RemoteApp as any)['__APP_VERSION__'] = __APP_VERSION__;
100
+
101
+ export function createRemoteComponent<T, E extends keyof T>(
102
+ lazyComponent: () => Promise<T>,
103
+ info?: {
104
+ export?: E;
105
+ },
106
+ ) {
107
+ type ExportType = T[E] extends (...args: any) => any
108
+ ? ReturnType<T[E]>
109
+ : never;
110
+ type RawComponentType = '__BRIDGE_FN__' extends keyof ExportType
111
+ ? ExportType['__BRIDGE_FN__'] extends (...args: any) => any
112
+ ? Parameters<ExportType['__BRIDGE_FN__']>[0]
113
+ : {}
114
+ : {};
115
+
116
+ return (
117
+ props: {
118
+ basename?: ProviderParams['basename'];
119
+ memoryRoute?: ProviderParams['memoryRoute'];
120
+ fallback: ReactNode;
121
+ } & RawComponentType,
122
+ ) => {
123
+ const exportName = info?.export || 'default';
124
+ const routerContextVal = useContext(UNSAFE_RouteContext);
125
+ let basename = '/';
126
+ if (
127
+ routerContextVal.matches[0] &&
128
+ routerContextVal.matches[0].pathnameBase
129
+ ) {
130
+ basename = routerContextVal.matches[0].pathnameBase;
131
+ }
132
+
133
+ const LazyComponent = useMemo(() => {
134
+ //@ts-ignore
135
+ return React.lazy(async () => {
136
+ LoggerInstance.log(`createRemoteComponent LazyComponent create >>>`, {
137
+ basename,
138
+ lazyComponent,
139
+ exportName,
140
+ props,
141
+ });
142
+ const m = (await lazyComponent()) as RemoteModule;
143
+ // @ts-ignore
144
+ const moduleName = m && m[Symbol.for('mf_module_id')];
145
+ LoggerInstance.log(
146
+ `createRemoteComponent LazyComponent loadRemote info >>>`,
147
+ { basename, name: moduleName, module: m, exportName, props },
148
+ );
149
+
150
+ // @ts-ignore
151
+ const exportFn = m[exportName] as any;
152
+
153
+ if (exportName in m && typeof exportFn === 'function') {
154
+ return {
155
+ default: () => (
156
+ <RemoteApp
157
+ name={moduleName}
158
+ {...info}
159
+ {...props}
160
+ providerInfo={exportFn}
161
+ basename={basename}
162
+ />
163
+ ),
164
+ };
165
+ }
166
+
167
+ throw Error('module not found');
168
+ });
169
+ }, [exportName, basename, props.memoryRoute]);
170
+
171
+ //@ts-ignore
172
+ return (
173
+ <React.Suspense fallback={props.fallback}>
174
+ <LazyComponent />
175
+ </React.Suspense>
176
+ );
177
+ };
178
+ }
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export { createRemoteComponent } from './create';
2
+ export { createBridgeComponent } from './provider';
3
+ export type {
4
+ ProviderParams,
5
+ RenderFnParams,
6
+ } from '@module-federation/bridge-shared';
@@ -0,0 +1,2 @@
1
+ /// <reference types='@modern-js/module-tools/types' />
2
+ /// <reference types='@modern-js/plugin-testing/types' />