@bleedingdev/modern-js-runtime 3.2.0-ultramodern.62 → 3.2.0-ultramodern.63

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.
Files changed (37) hide show
  1. package/dist/cjs/boundary-debugger/index.js +99 -22
  2. package/dist/cjs/core/server/federatedCss.js +47 -0
  3. package/dist/cjs/core/server/stream/beforeTemplate.js +6 -1
  4. package/dist/cjs/core/server/stream/beforeTemplate.worker.js +6 -1
  5. package/dist/cjs/core/server/stream/createReadableStream.js +4 -2
  6. package/dist/cjs/core/server/stream/createReadableStream.worker.js +3 -2
  7. package/dist/cjs/core/server/stream/shared.js +2 -1
  8. package/dist/cjs/core/server/string/index.js +2 -1
  9. package/dist/cjs/core/server/string/loadable.js +18 -7
  10. package/dist/cjs/router/cli/code/tanstackTypes.js +15 -0
  11. package/dist/esm/boundary-debugger/index.mjs +99 -22
  12. package/dist/esm/core/server/federatedCss.mjs +13 -0
  13. package/dist/esm/core/server/stream/beforeTemplate.mjs +6 -1
  14. package/dist/esm/core/server/stream/beforeTemplate.worker.mjs +6 -1
  15. package/dist/esm/core/server/stream/createReadableStream.mjs +4 -2
  16. package/dist/esm/core/server/stream/createReadableStream.worker.mjs +3 -2
  17. package/dist/esm/core/server/stream/shared.mjs +2 -1
  18. package/dist/esm/core/server/string/index.mjs +2 -1
  19. package/dist/esm/core/server/string/loadable.mjs +18 -7
  20. package/dist/esm/router/cli/code/tanstackTypes.mjs +15 -0
  21. package/dist/esm-node/boundary-debugger/index.mjs +99 -22
  22. package/dist/esm-node/core/server/federatedCss.mjs +14 -0
  23. package/dist/esm-node/core/server/stream/beforeTemplate.mjs +6 -1
  24. package/dist/esm-node/core/server/stream/beforeTemplate.worker.mjs +6 -1
  25. package/dist/esm-node/core/server/stream/createReadableStream.mjs +4 -2
  26. package/dist/esm-node/core/server/stream/createReadableStream.worker.mjs +3 -2
  27. package/dist/esm-node/core/server/stream/shared.mjs +2 -1
  28. package/dist/esm-node/core/server/string/index.mjs +2 -1
  29. package/dist/esm-node/core/server/string/loadable.mjs +18 -7
  30. package/dist/esm-node/router/cli/code/tanstackTypes.mjs +15 -0
  31. package/dist/types/boundary-debugger/index.d.ts +3 -0
  32. package/dist/types/core/server/federatedCss.d.ts +5 -0
  33. package/dist/types/core/server/stream/beforeTemplate.d.ts +1 -0
  34. package/dist/types/core/server/stream/beforeTemplate.worker.d.ts +1 -0
  35. package/dist/types/core/server/stream/shared.d.ts +1 -0
  36. package/dist/types/core/server/string/loadable.d.ts +1 -0
  37. package/package.json +9 -9
@@ -1,12 +1,14 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useMemo, useState } from "react";
3
3
  const defaultStorageKey = 'modernjs:boundary-debugger:enabled';
4
+ const queryParamName = 'modern-boundaries';
5
+ const boundarySelector = '[data-modern-boundary-id]';
4
6
  const defaultLabels = {
5
7
  cs: {
6
- toggle: 'zobrazit hranice verticalů'
8
+ toggle: 'zobrazit hranice týmů'
7
9
  },
8
10
  en: {
9
- toggle: 'show vertical boundaries'
11
+ toggle: 'show team boundaries'
10
12
  }
11
13
  };
12
14
  const palette = [
@@ -16,18 +18,64 @@ const palette = [
16
18
  '#7c8cff',
17
19
  '#29b6f6'
18
20
  ];
19
- const readEnabled = (storageKey, fallback)=>{
21
+ const readStoredEnabled = (storageKey, fallback)=>{
20
22
  if ("u" < typeof window) return fallback;
21
- const stored = window.localStorage.getItem(storageKey);
22
- return null === stored ? fallback : 'true' === stored;
23
+ try {
24
+ const stored = window.localStorage.getItem(storageKey);
25
+ return null === stored ? fallback : 'true' === stored;
26
+ } catch {
27
+ return fallback;
28
+ }
29
+ };
30
+ const writeStoredEnabled = (storageKey, enabled)=>{
31
+ if ("u" < typeof window) return;
32
+ try {
33
+ window.localStorage.setItem(storageKey, String(enabled));
34
+ } catch {}
35
+ };
36
+ const parseEnabledOverride = (value)=>{
37
+ if (null === value) return;
38
+ const normalized = value.toLowerCase();
39
+ if ('1' === normalized || 'true' === normalized) return true;
40
+ if ('0' === normalized || 'false' === normalized) return false;
41
+ };
42
+ const readQueryEnabledOverride = ()=>{
43
+ if ("u" < typeof window) return;
44
+ try {
45
+ return parseEnabledOverride(new URLSearchParams(window.location.search).get(queryParamName));
46
+ } catch {
47
+ return;
48
+ }
23
49
  };
24
50
  const detectLanguage = ()=>{
25
51
  if ("u" < typeof document) return 'en';
26
52
  const htmlLanguage = document.documentElement.lang;
27
53
  if (htmlLanguage) return htmlLanguage.split('-')[0] || 'en';
54
+ if ("u" < typeof window) return 'en';
28
55
  return window.location.pathname.split('/').filter(Boolean)[0] || 'en';
29
56
  };
30
- function BoundaryDebugger({ enabledByDefault = false, labels = defaultLabels, metadata, storageKey = defaultStorageKey }) {
57
+ const hashBoundaryId = (id)=>{
58
+ let hash = 0;
59
+ for(let index = 0; index < id.length; index++)hash = 31 * hash + id.charCodeAt(index) >>> 0;
60
+ return hash;
61
+ };
62
+ const formatRectKey = (rect)=>[
63
+ Math.round(100 * rect.left) / 100,
64
+ Math.round(100 * rect.top) / 100,
65
+ Math.round(100 * rect.width) / 100,
66
+ Math.round(100 * rect.height) / 100
67
+ ].join(':');
68
+ const getBoundaryId = (element)=>element.dataset.modernBoundaryId ?? element.dataset.mfRemote ?? element.getAttribute('data-mf-remote') ?? void 0;
69
+ const collectBoundaryElements = (legacySelector)=>{
70
+ const elements = new Set();
71
+ for (const element of document.querySelectorAll(boundarySelector))elements.add(element);
72
+ if (!legacySelector) return Array.from(elements);
73
+ try {
74
+ for (const element of document.querySelectorAll(legacySelector))elements.add(element);
75
+ } catch {}
76
+ return Array.from(elements);
77
+ };
78
+ function BoundaryDebugger({ controlMode = 'visible', enabledByDefault = false, labels = defaultLabels, legacySelector, metadata, storageKey = defaultStorageKey }) {
31
79
  const [mounted, setMounted] = useState(false);
32
80
  const [enabled, setEnabled] = useState(false);
33
81
  const [boxes, setBoxes] = useState([]);
@@ -42,17 +90,18 @@ function BoundaryDebugger({ enabledByDefault = false, labels = defaultLabels, me
42
90
  metadata
43
91
  ]);
44
92
  const language = mounted ? detectLanguage() : 'en';
45
- const toggleLabel = labels[language]?.toggle ?? labels.en?.toggle ?? defaultLabels.en?.toggle ?? 'show vertical boundaries';
93
+ const toggleLabel = labels[language]?.toggle ?? labels.en?.toggle ?? defaultLabels.en?.toggle ?? 'show team boundaries';
46
94
  useEffect(()=>{
47
95
  setMounted(true);
48
- setEnabled(readEnabled(storageKey, enabledByDefault));
96
+ const queryOverride = readQueryEnabledOverride();
97
+ setEnabled(queryOverride ?? readStoredEnabled(storageKey, enabledByDefault));
49
98
  }, [
50
99
  enabledByDefault,
51
100
  storageKey
52
101
  ]);
53
102
  useEffect(()=>{
54
103
  if (!mounted) return;
55
- window.localStorage.setItem(storageKey, String(enabled));
104
+ writeStoredEnabled(storageKey, enabled);
56
105
  }, [
57
106
  enabled,
58
107
  mounted,
@@ -61,28 +110,38 @@ function BoundaryDebugger({ enabledByDefault = false, labels = defaultLabels, me
61
110
  useEffect(()=>{
62
111
  if (!enabled) return void setBoxes([]);
63
112
  const readBoxes = ()=>{
64
- const nextBoxes = Array.from(document.querySelectorAll('[data-modern-boundary-id]')).map((element, index)=>{
65
- const boundaryId = element.dataset.modernBoundaryId;
113
+ const seenBoxes = new Set();
114
+ const nextBoxes = collectBoundaryElements(legacySelector).map((element)=>{
115
+ const boundaryId = getBoundaryId(element);
66
116
  if (!boundaryId) return;
67
117
  const rect = element.getBoundingClientRect();
68
118
  if (rect.width <= 0 || rect.height <= 0) return;
119
+ const rectKey = formatRectKey(rect);
120
+ const boxKey = `${boundaryId}:${rectKey}`;
121
+ if (seenBoxes.has(boxKey)) return;
122
+ seenBoxes.add(boxKey);
69
123
  const boundary = boundaries.get(boundaryId);
70
- const color = boundary?.color ?? palette[index % palette.length];
71
- return {
124
+ const color = boundary?.color ?? palette[hashBoundaryId(boundaryId) % palette.length];
125
+ const label = boundary?.label ?? boundary?.appId ?? boundaryId;
126
+ const expose = element.dataset.modernMfExpose;
127
+ const detail = expose && expose !== label && expose !== boundaryId ? expose : void 0;
128
+ const box = {
72
129
  color,
73
130
  height: rect.height,
74
- id: `${boundaryId}-${index}`,
75
- label: boundary?.label ?? boundaryId,
131
+ id: boxKey,
132
+ label,
76
133
  left: rect.left,
77
134
  top: rect.top,
78
135
  width: rect.width
79
136
  };
137
+ if (detail) box.detail = detail;
138
+ return box;
80
139
  }).filter((box)=>void 0 !== box);
81
140
  setBoxes(nextBoxes);
82
141
  };
83
142
  readBoxes();
84
143
  const resizeObserver = "u" < typeof ResizeObserver ? void 0 : new ResizeObserver(readBoxes);
85
- for (const element of document.querySelectorAll('[data-modern-boundary-id]'))resizeObserver?.observe(element);
144
+ for (const element of collectBoundaryElements(legacySelector))resizeObserver?.observe(element);
86
145
  const mutationObserver = new MutationObserver(readBoxes);
87
146
  mutationObserver.observe(document.body, {
88
147
  childList: true,
@@ -98,12 +157,14 @@ function BoundaryDebugger({ enabledByDefault = false, labels = defaultLabels, me
98
157
  };
99
158
  }, [
100
159
  boundaries,
101
- enabled
160
+ enabled,
161
+ legacySelector
102
162
  ]);
103
163
  if (!mounted) return null;
164
+ const shouldRenderToggle = 'visible' === controlMode || 'hidden-when-off' === controlMode && enabled;
104
165
  return /*#__PURE__*/ jsxs(Fragment, {
105
166
  children: [
106
- /*#__PURE__*/ jsxs("label", {
167
+ shouldRenderToggle ? /*#__PURE__*/ jsxs("label", {
107
168
  style: {
108
169
  alignItems: 'center',
109
170
  background: 'rgba(255, 255, 255, 0.96)',
@@ -130,7 +191,7 @@ function BoundaryDebugger({ enabledByDefault = false, labels = defaultLabels, me
130
191
  children: toggleLabel
131
192
  })
132
193
  ]
133
- }),
194
+ }) : null,
134
195
  enabled ? /*#__PURE__*/ jsx("div", {
135
196
  "aria-hidden": "true",
136
197
  children: boxes.map((box)=>/*#__PURE__*/ jsx("div", {
@@ -146,19 +207,35 @@ function BoundaryDebugger({ enabledByDefault = false, labels = defaultLabels, me
146
207
  width: box.width,
147
208
  zIndex: 2147482999
148
209
  },
149
- children: /*#__PURE__*/ jsx("span", {
210
+ children: /*#__PURE__*/ jsxs("span", {
150
211
  style: {
151
212
  background: box.color,
152
213
  borderRadius: 999,
153
214
  color: '#111827',
154
- font: '800 11px/1 system-ui, sans-serif',
215
+ display: 'grid',
216
+ font: '800 11px/1.1 system-ui, sans-serif',
217
+ gap: 3,
218
+ maxWidth: 'min(280px, calc(100vw - 24px))',
155
219
  padding: '5px 8px',
156
220
  position: 'absolute',
157
221
  right: 4,
158
222
  top: 4,
159
223
  whiteSpace: 'nowrap'
160
224
  },
161
- children: box.label
225
+ children: [
226
+ /*#__PURE__*/ jsx("span", {
227
+ children: box.label
228
+ }),
229
+ box.detail ? /*#__PURE__*/ jsx("span", {
230
+ style: {
231
+ font: '700 10px/1.1 system-ui, sans-serif',
232
+ opacity: 0.82,
233
+ overflow: 'hidden',
234
+ textOverflow: 'ellipsis'
235
+ },
236
+ children: box.detail
237
+ }) : null
238
+ ]
162
239
  })
163
240
  }, box.id))
164
241
  }) : null
@@ -0,0 +1,13 @@
1
+ import { attributesToString } from "./utils.mjs";
2
+ const createFederatedCssLinks = (assets, options)=>{
3
+ if (!assets?.length) return '';
4
+ const seen = new Set(options.existingAssets || []);
5
+ const attributes = attributesToString(options.attributes || {});
6
+ const links = [];
7
+ for (const asset of assets)if (!(!asset || seen.has(asset) || options.template.includes(asset))) {
8
+ seen.add(asset);
9
+ links.push(`<link${attributes} href="${asset}" rel="stylesheet" />`);
10
+ }
11
+ return links.join('');
12
+ };
13
+ export { createFederatedCssLinks };
@@ -2,6 +2,7 @@ import { matchRoutes } from "@modern-js/runtime-utils/router";
2
2
  import react_helmet from "react-helmet";
3
3
  import { getRouterMatchedRouteIds } from "../../../router/runtime/lifecycle.mjs";
4
4
  import { CHUNK_CSS_PLACEHOLDER } from "../constants.mjs";
5
+ import { createFederatedCssLinks } from "../federatedCss.mjs";
5
6
  import { createReplaceHelemt } from "../helmet.mjs";
6
7
  import { buildHtml } from "../shared.mjs";
7
8
  import { checkIsNode, safeReplace } from "../utils.mjs";
@@ -17,7 +18,7 @@ const checkIsInline = (chunk, enableInline)=>{
17
18
  return Boolean(enableInline);
18
19
  };
19
20
  async function buildShellBeforeTemplate(beforeAppTemplate, options) {
20
- const { config, runtimeContext, styledComponentsStyleTags, entryName } = options;
21
+ const { config, runtimeContext, styledComponentsStyleTags, entryName, moduleFederationCssAssets } = options;
21
22
  const helmetData = react_helmet.renderStatic();
22
23
  const callbacks = [
23
24
  createReplaceHelemt(helmetData),
@@ -27,6 +28,10 @@ async function buildShellBeforeTemplate(beforeAppTemplate, options) {
27
28
  async function injectCss(template, entryName, styledComponentsStyleTags) {
28
29
  let css = await getCssChunks();
29
30
  if (styledComponentsStyleTags) css += styledComponentsStyleTags;
31
+ css += createFederatedCssLinks(moduleFederationCssAssets, {
32
+ template,
33
+ existingAssets: css.match(/href="([^"]+)"/g)?.map((item)=>item.replace(/^href="/, '').replace(/"$/, ''))
34
+ });
30
35
  return safeReplace(template, CHUNK_CSS_PLACEHOLDER, css);
31
36
  async function getCssChunks() {
32
37
  const { routeManifest, routerContext, routes } = runtimeContext;
@@ -2,6 +2,7 @@ import { matchRoutes } from "@modern-js/runtime-utils/router";
2
2
  import react_helmet from "react-helmet";
3
3
  import { getRouterMatchedRouteIds } from "../../../router/runtime/lifecycle.mjs";
4
4
  import { CHUNK_CSS_PLACEHOLDER } from "../constants.mjs";
5
+ import { createFederatedCssLinks } from "../federatedCss.mjs";
5
6
  import { createReplaceHelemt } from "../helmet.mjs";
6
7
  import { buildHtml } from "../shared.mjs";
7
8
  import { safeReplace } from "../utils.mjs";
@@ -11,7 +12,7 @@ const checkIsInline = (chunk, enableInline)=>{
11
12
  return Boolean(enableInline);
12
13
  };
13
14
  async function buildShellBeforeTemplate(beforeAppTemplate, options) {
14
- const { config, runtimeContext, styledComponentsStyleTags, entryName } = options;
15
+ const { config, runtimeContext, styledComponentsStyleTags, entryName, moduleFederationCssAssets } = options;
15
16
  const helmetData = react_helmet.renderStatic();
16
17
  const callbacks = [
17
18
  createReplaceHelemt(helmetData),
@@ -21,6 +22,10 @@ async function buildShellBeforeTemplate(beforeAppTemplate, options) {
21
22
  async function injectCss(template, entryName, styledComponentsStyleTags) {
22
23
  let css = await getCssChunks();
23
24
  if (styledComponentsStyleTags) css += styledComponentsStyleTags;
25
+ css += createFederatedCssLinks(moduleFederationCssAssets, {
26
+ template,
27
+ existingAssets: css.match(/href="([^"]+)"/g)?.map((item)=>item.replace(/^href="/, '').replace(/"$/, ''))
28
+ });
24
29
  return safeReplace(template, CHUNK_CSS_PLACEHOLDER, css);
25
30
  async function getCssChunks() {
26
31
  const { routeManifest, routerContext, routes } = runtimeContext;
@@ -15,7 +15,7 @@ const defaultExtender = {
15
15
  };
16
16
  const createReadableStreamFromElement = async (request, rootElement, options)=>{
17
17
  const { renderToPipeableStream } = await import("react-dom/server");
18
- const { runtimeContext, htmlTemplate, config, ssrConfig, entryName } = options;
18
+ const { runtimeContext, htmlTemplate, config, ssrConfig, entryName, moduleFederationCssAssets } = options;
19
19
  let shellChunkStatus = ShellChunkStatus.START;
20
20
  let renderLevel = RenderLevel.SERVER_RENDER;
21
21
  const forceStream2String = Boolean(process.env.MODERN_JS_STREAM_TO_STRING);
@@ -52,6 +52,7 @@ const createReadableStreamFromElement = async (request, rootElement, options)=>{
52
52
  runtimeContext,
53
53
  config,
54
54
  entryName,
55
+ moduleFederationCssAssets,
55
56
  styledComponentsStyleTags
56
57
  }).then(({ shellAfter, shellBefore })=>{
57
58
  const pendingScripts = [];
@@ -109,7 +110,8 @@ const createReadableStreamFromElement = async (request, rootElement, options)=>{
109
110
  renderLevel,
110
111
  runtimeContext,
111
112
  entryName,
112
- config
113
+ config,
114
+ moduleFederationCssAssets
113
115
  }).then(({ shellAfter, shellBefore })=>{
114
116
  const fallbackHtml = `${shellBefore}${shellAfter}`;
115
117
  const readableStream = getReadableStreamFromString(fallbackHtml);
@@ -8,14 +8,15 @@ import { getTemplates } from "./template.mjs";
8
8
  const createReadableStreamFromElement = async (request, rootElement, options)=>{
9
9
  let shellChunkStatus = ShellChunkStatus.START;
10
10
  const chunkVec = [];
11
- const { htmlTemplate, runtimeContext, config, ssrConfig, entryName, rscManifest, rscRoot } = options;
11
+ const { htmlTemplate, runtimeContext, config, ssrConfig, entryName, moduleFederationCssAssets, rscManifest, rscRoot } = options;
12
12
  const { shellBefore, shellAfter } = await getTemplates(htmlTemplate, {
13
13
  renderLevel: RenderLevel.SERVER_RENDER,
14
14
  runtimeContext,
15
15
  ssrConfig,
16
16
  request,
17
17
  config,
18
- entryName
18
+ entryName,
19
+ moduleFederationCssAssets
19
20
  });
20
21
  try {
21
22
  const readableOriginal = await renderSSRStream(rootElement, {
@@ -63,7 +63,7 @@ function createRenderStreaming(createReadableStreamPromise) {
63
63
  const end = time();
64
64
  const { runtimeContext, config, resource } = options;
65
65
  const { onError, onTiming } = options;
66
- const { htmlTemplate, entryName } = resource;
66
+ const { htmlTemplate, entryName, moduleFederationCssAssets } = resource;
67
67
  const ssrConfig = getSSRConfigByEntry(entryName, config.ssr, config.ssrByEntries);
68
68
  const StreamServerRootWrapper = ({ children })=>/*#__PURE__*/ jsxs(Fragment, {
69
69
  children: [
@@ -83,6 +83,7 @@ function createRenderStreaming(createReadableStreamPromise) {
83
83
  runtimeContext,
84
84
  ssrConfig,
85
85
  entryName,
86
+ moduleFederationCssAssets,
86
87
  rscClientManifest: options.rscClientManifest,
87
88
  rscSSRManifest: options.rscSSRManifest,
88
89
  rscServerManifest: options.rscServerManifest,
@@ -19,7 +19,7 @@ const renderString = async (request, serverRoot, options)=>{
19
19
  onTiming
20
20
  };
21
21
  const routerContext = runtimeContext.routerContext;
22
- const { htmlTemplate, entryName, loadableStats, routeManifest } = resource;
22
+ const { htmlTemplate, entryName, loadableStats, routeManifest, moduleFederationCssAssets } = resource;
23
23
  const ssrConfig = getSSRConfigByEntry(entryName, config.ssr, config.ssrByEntries);
24
24
  const chunkSet = {
25
25
  renderLevel: RenderLevel.CLIENT_RENDER,
@@ -35,6 +35,7 @@ const renderString = async (request, serverRoot, options)=>{
35
35
  runtimeContext,
36
36
  template: htmlTemplate,
37
37
  entryName,
38
+ moduleFederationCssAssets,
38
39
  chunkSet,
39
40
  config
40
41
  }),
@@ -1,5 +1,6 @@
1
1
  import { ChunkExtractor } from "@loadable/server";
2
2
  import { getRouterMatchedRouteIds } from "../../../router/runtime/lifecycle.mjs";
3
+ import { createFederatedCssLinks } from "../federatedCss.mjs";
3
4
  import { attributesToString, checkIsNode } from "../utils.mjs";
4
5
  const extname = (uri)=>{
5
6
  if ('string' != typeof uri || !uri.includes('.')) return '';
@@ -48,20 +49,21 @@ class LoadableCollector {
48
49
  return this.extractor.collectChunks(comopnent);
49
50
  }
50
51
  async effect() {
51
- if (!this.extractor) return;
52
52
  const { extractor, options } = this;
53
53
  const { entryName, config } = options;
54
54
  const asyncChunks = [];
55
- if (config.enableAsyncEntry) try {
55
+ if (extractor && config.enableAsyncEntry) try {
56
56
  asyncChunks.push(...extractor.getChunkAssets([
57
57
  `async-${entryName}`
58
58
  ]));
59
59
  } catch (e) {}
60
- const chunks = [].concat(asyncChunks).concat(extractor.getChunkAssets(extractor.chunks)).concat(this.getMatchedRouteChunks());
60
+ const chunks = [].concat(asyncChunks).concat(extractor ? extractor.getChunkAssets(extractor.chunks) : []).concat(this.getMatchedRouteChunks());
61
61
  const scriptChunks = generateChunks(chunks, 'js');
62
62
  const styleChunks = generateChunks(chunks, 'css');
63
- this.emitLoadableScripts(extractor);
64
- await this.emitScriptAssets(scriptChunks);
63
+ if (extractor) {
64
+ this.emitLoadableScripts(extractor);
65
+ await this.emitScriptAssets(scriptChunks);
66
+ }
65
67
  await this.emitStyleAssets(styleChunks);
66
68
  }
67
69
  emitLoadableScripts(extractor) {
@@ -96,19 +98,28 @@ class LoadableCollector {
96
98
  chunkSet.jsChunk += scripts.filter((script)=>Boolean(script)).join('');
97
99
  }
98
100
  async emitStyleAssets(chunks) {
99
- const { template, chunkSet, config, entryName } = this.options;
101
+ const { template, chunkSet, config, moduleFederationCssAssets } = this.options;
100
102
  const { inlineStyles } = config;
101
103
  const atrributes = attributesToString(this.generateAttributes());
102
104
  const linkRegExp = /<link .*?href="([^"]+)".*?>/g;
103
105
  const matchs = template.matchAll(linkRegExp);
104
106
  const existedLinks = [];
105
107
  for (const match of matchs)existedLinks.push(match[1]);
106
- const css = await Promise.all(chunks.filter((chunk)=>!existedLinks.includes(chunk.url) && !this.existsAssets?.includes(chunk.path)).map(async (chunk)=>{
108
+ const emittedChunks = chunks.filter((chunk)=>!existedLinks.includes(chunk.url) && !this.existsAssets?.includes(chunk.path));
109
+ const css = await Promise.all(emittedChunks.map(async (chunk)=>{
107
110
  const link = `<link${atrributes} href="${chunk.url}" rel="stylesheet" />`;
108
111
  if (checkIsNode() && checkIsInline(chunk, inlineStyles)) return readAsset(chunk).then((content)=>`<style>${content}</style>`).catch((_)=>link);
109
112
  return link;
110
113
  }));
111
114
  chunkSet.cssChunk += css.filter((css)=>Boolean(css)).join('');
115
+ chunkSet.cssChunk += createFederatedCssLinks(moduleFederationCssAssets, {
116
+ template,
117
+ attributes: this.generateAttributes(),
118
+ existingAssets: [
119
+ ...existedLinks,
120
+ ...emittedChunks.map((chunk)=>chunk.url)
121
+ ]
122
+ });
112
123
  }
113
124
  generateAttributes(extraAtr = {}) {
114
125
  const { config } = this.options;
@@ -77,10 +77,21 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
77
77
  const topLevel = rootModern ? rootModern.children || [] : routes;
78
78
  const imports = [];
79
79
  const statements = [];
80
+ const componentImportMap = new Map();
80
81
  const loaderImportMap = new Map();
81
82
  const usedRouteVarNames = new Set();
83
+ let componentIndex = 0;
82
84
  let loaderIndex = 0;
83
85
  let routeIndex = 0;
86
+ const getImportNameForComponent = (componentPath)=>{
87
+ if ('string' != typeof componentPath || 0 === componentPath.length) return null;
88
+ const existing = componentImportMap.get(componentPath);
89
+ if (existing) return existing;
90
+ const componentName = `component_${componentIndex++}`;
91
+ imports.push(`import ${componentName} from ${quote(componentPath)};`);
92
+ componentImportMap.set(componentPath, componentName);
93
+ return componentName;
94
+ };
84
95
  const getImportNamesForLoader = async (aliasedNoExtPath, inline, hasAction)=>{
85
96
  const key = `${inline ? 'inline' : 'default'}:${hasAction ? 'action' : 'loader'}:${aliasedNoExtPath}`;
86
97
  const existing = loaderImportMap.get(key);
@@ -137,6 +148,8 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
137
148
  const routeOpts = [
138
149
  `getParentRoute: () => ${parentVar},`
139
150
  ];
151
+ const componentName = getImportNameForComponent(route._component);
152
+ if (componentName) routeOpts.push(`component: ${componentName},`);
140
153
  if (isPathlessLayout(route)) {
141
154
  const id = route.id;
142
155
  routeOpts.push(`id: ${quote(id || 'pathless')},`);
@@ -174,6 +187,8 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
174
187
  route
175
188
  })));
176
189
  const rootOpts = [];
190
+ const rootComponentName = getImportNameForComponent(rootModern?._component);
191
+ if (rootComponentName) rootOpts.push(`component: ${rootComponentName},`);
177
192
  if (rootLoaderName) rootOpts.push(`loader: modernLoaderToTanstack({ hasSplat: false }, ${rootLoaderName}),`);
178
193
  const routerGenTs = `/* eslint-disable */
179
194
  // This file is auto-generated by Modern.js. Do not edit manually.