@module-federation/bridge-vue3 0.19.1 → 0.21.0

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 CHANGED
@@ -7,7 +7,7 @@
7
7
  "url": "git+https://github.com/module-federation/core.git",
8
8
  "directory": "packages/bridge/vue3-bridge"
9
9
  },
10
- "version": "0.19.1",
10
+ "version": "0.21.0",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
@@ -32,16 +32,16 @@
32
32
  "vue-router": "=4"
33
33
  },
34
34
  "dependencies": {
35
- "@module-federation/bridge-shared": "0.19.1",
36
- "@module-federation/sdk": "0.19.1",
37
- "@module-federation/runtime": "0.19.1"
35
+ "@module-federation/sdk": "0.21.0",
36
+ "@module-federation/runtime": "0.21.0",
37
+ "@module-federation/bridge-shared": "0.21.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/react": "^18.3.11",
41
41
  "@vitejs/plugin-vue": "^5.0.4",
42
42
  "@vitejs/plugin-vue-jsx": "^4.0.0",
43
43
  "typescript": "^5.2.2",
44
- "vite": "^5.4.18",
44
+ "vite": "^5.4.20",
45
45
  "vite-plugin-dts": "^4.3.0",
46
46
  "vue": "^3.4.21",
47
47
  "vue-router": "4.4.5",
@@ -50,6 +50,7 @@
50
50
  "scripts": {
51
51
  "dev": "vite",
52
52
  "build": "vite build",
53
- "preview": "vite preview"
53
+ "preview": "vite preview",
54
+ "test": "vitest"
54
55
  }
55
56
  }
package/src/provider.ts CHANGED
@@ -3,6 +3,7 @@ import * as VueRouter from 'vue-router';
3
3
  import { RenderFnParams } from '@module-federation/bridge-shared';
4
4
  import { LoggerInstance } from './utils';
5
5
  import { getInstance } from '@module-federation/runtime';
6
+ import { processRoutes } from './routeUtils';
6
7
 
7
8
  declare const __APP_VERSION__: string;
8
9
 
@@ -58,22 +59,12 @@ export function createBridgeComponent(bridgeInfo: ProviderFnParams) {
58
59
  ...extraProps,
59
60
  });
60
61
  if (bridgeOptions?.router) {
61
- let history;
62
- let routes = bridgeOptions.router.getRoutes();
63
-
64
- if (info.memoryRoute) {
65
- history = VueRouter.createMemoryHistory(info.basename);
66
- } else if (info.hashRoute) {
67
- history = VueRouter.createWebHashHistory();
68
- routes = routes.map((route) => {
69
- return {
70
- ...route,
71
- path: info.basename + route.path,
72
- };
73
- });
74
- } else {
75
- history = VueRouter.createWebHistory(info.basename);
76
- }
62
+ const { history, routes } = processRoutes({
63
+ router: bridgeOptions.router,
64
+ basename: info.basename,
65
+ memoryRoute: info.memoryRoute,
66
+ hashRoute: info.hashRoute,
67
+ });
77
68
 
78
69
  const router = VueRouter.createRouter({
79
70
  ...bridgeOptions.router.options,
@@ -0,0 +1,139 @@
1
+ import * as VueRouter from 'vue-router';
2
+
3
+ export interface RouteProcessingOptions {
4
+ router: VueRouter.Router;
5
+ basename?: string;
6
+ memoryRoute?: boolean | { entryPath: string };
7
+ hashRoute?: boolean;
8
+ }
9
+
10
+ export interface RouteProcessingResult {
11
+ history: VueRouter.RouterHistory;
12
+ routes: VueRouter.RouteRecordNormalized[];
13
+ }
14
+
15
+ /**
16
+ * Add basename prefix to all nested routes recursively
17
+ *
18
+ * @param routes - route configuration array
19
+ * @param basename - base path prefix
20
+ * @returns processed route configuration
21
+ */
22
+ function addBasenameToNestedRoutes(
23
+ routes: VueRouter.RouteRecordNormalized[],
24
+ basename: string,
25
+ ): VueRouter.RouteRecordNormalized[] {
26
+ return routes.map((route) => {
27
+ const updatedRoute: VueRouter.RouteRecordNormalized = {
28
+ ...route,
29
+ path: basename + route.path,
30
+ };
31
+
32
+ // Recursively process child routes
33
+ if (route.children && route.children.length > 0) {
34
+ updatedRoute.children = addBasenameToNestedRoutes(
35
+ route.children as VueRouter.RouteRecordNormalized[],
36
+ basename,
37
+ );
38
+ }
39
+
40
+ return updatedRoute;
41
+ });
42
+ }
43
+
44
+ /**
45
+ * Route processing solution based on path analysis
46
+ *
47
+ * @param options - route processing options
48
+ * @returns processed history and routes
49
+ */
50
+ export function processRoutes(
51
+ options: RouteProcessingOptions,
52
+ ): RouteProcessingResult {
53
+ const { router, basename, memoryRoute, hashRoute } = options;
54
+
55
+ // Sort routes, try to process parent route first
56
+ const flatRoutes = router
57
+ .getRoutes()
58
+ .sort(
59
+ (a, b) =>
60
+ a.path.split('/').filter((p) => p).length -
61
+ b.path.split('/').filter((p) => p).length,
62
+ );
63
+
64
+ // Use Map/Set for O(1) lookup performance
65
+ const flatRoutesMap = new Map<string, VueRouter.RouteRecordNormalized>();
66
+ const processedRoutes = new Set<VueRouter.RouteRecordNormalized>();
67
+
68
+ flatRoutes.forEach((route) => {
69
+ flatRoutesMap.set(route.path, route);
70
+ });
71
+
72
+ /**
73
+ * Normalize path by removing double slashes and trailing slashes
74
+ */
75
+ const normalizePath = (prefix: string, childPath: string): string => {
76
+ const fullPath = `${prefix}/${childPath}`;
77
+ return fullPath.replace(/\/+/g, '/').replace(/\/$/, '') || '/';
78
+ };
79
+
80
+ const processChildren = (
81
+ route: VueRouter.RouteRecordNormalized,
82
+ prefix = '',
83
+ ): VueRouter.RouteRecordNormalized => {
84
+ if (!route.children || route.children.length === 0) {
85
+ return route;
86
+ }
87
+
88
+ for (let j = 0; j < route.children.length; j++) {
89
+ const child = route.children[j];
90
+ const fullPath = normalizePath(prefix, child.path);
91
+ const childRoute = flatRoutesMap.get(fullPath);
92
+
93
+ if (childRoute && !processedRoutes.has(childRoute)) {
94
+ // Create a new optimized route object with relative path for nested routes
95
+ const relativeChildRoute: VueRouter.RouteRecordNormalized = {
96
+ ...childRoute,
97
+ path: child.path, // Keep the original relative path from static route
98
+ };
99
+
100
+ route.children[j] = relativeChildRoute;
101
+ processedRoutes.add(childRoute);
102
+
103
+ processChildren(relativeChildRoute, fullPath);
104
+ }
105
+ }
106
+
107
+ return route;
108
+ };
109
+
110
+ // Reconstruct nested structure
111
+ let routes: VueRouter.RouteRecordNormalized[] = [];
112
+
113
+ for (const route of flatRoutes) {
114
+ if (!processedRoutes.has(route)) {
115
+ const processedRoute = processChildren(route, route.path);
116
+ processedRoutes.add(route);
117
+ routes.push(processedRoute);
118
+ }
119
+ }
120
+
121
+ let history: VueRouter.RouterHistory;
122
+ if (memoryRoute) {
123
+ // Memory route mode
124
+ history = VueRouter.createMemoryHistory(basename);
125
+ } else if (hashRoute) {
126
+ // Hash route mode
127
+ history = VueRouter.createWebHashHistory();
128
+ // Recursively process nested routes and add basename prefix to all paths
129
+ if (basename) routes = addBasenameToNestedRoutes(routes, basename);
130
+ } else {
131
+ // Default Web History mode
132
+ history = VueRouter.createWebHistory(basename);
133
+ }
134
+
135
+ return {
136
+ history,
137
+ routes,
138
+ };
139
+ }