@bleedingdev/modern-js-runtime 3.2.0-ultramodern.61 → 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.
- package/dist/cjs/boundary-debugger/index.js +99 -22
- package/dist/cjs/core/server/federatedCss.js +47 -0
- package/dist/cjs/core/server/stream/beforeTemplate.js +6 -1
- package/dist/cjs/core/server/stream/beforeTemplate.worker.js +6 -1
- package/dist/cjs/core/server/stream/createReadableStream.js +4 -2
- package/dist/cjs/core/server/stream/createReadableStream.worker.js +3 -2
- package/dist/cjs/core/server/stream/shared.js +2 -1
- package/dist/cjs/core/server/string/index.js +2 -1
- package/dist/cjs/core/server/string/loadable.js +18 -7
- package/dist/cjs/router/cli/code/tanstackTypes.js +15 -0
- package/dist/esm/boundary-debugger/index.mjs +99 -22
- package/dist/esm/core/server/federatedCss.mjs +13 -0
- package/dist/esm/core/server/stream/beforeTemplate.mjs +6 -1
- package/dist/esm/core/server/stream/beforeTemplate.worker.mjs +6 -1
- package/dist/esm/core/server/stream/createReadableStream.mjs +4 -2
- package/dist/esm/core/server/stream/createReadableStream.worker.mjs +3 -2
- package/dist/esm/core/server/stream/shared.mjs +2 -1
- package/dist/esm/core/server/string/index.mjs +2 -1
- package/dist/esm/core/server/string/loadable.mjs +18 -7
- package/dist/esm/router/cli/code/tanstackTypes.mjs +15 -0
- package/dist/esm-node/boundary-debugger/index.mjs +99 -22
- package/dist/esm-node/core/server/federatedCss.mjs +14 -0
- package/dist/esm-node/core/server/stream/beforeTemplate.mjs +6 -1
- package/dist/esm-node/core/server/stream/beforeTemplate.worker.mjs +6 -1
- package/dist/esm-node/core/server/stream/createReadableStream.mjs +4 -2
- package/dist/esm-node/core/server/stream/createReadableStream.worker.mjs +3 -2
- package/dist/esm-node/core/server/stream/shared.mjs +2 -1
- package/dist/esm-node/core/server/string/index.mjs +2 -1
- package/dist/esm-node/core/server/string/loadable.mjs +18 -7
- package/dist/esm-node/router/cli/code/tanstackTypes.mjs +15 -0
- package/dist/types/boundary-debugger/index.d.ts +3 -0
- package/dist/types/core/server/federatedCss.d.ts +5 -0
- package/dist/types/core/server/stream/beforeTemplate.d.ts +1 -0
- package/dist/types/core/server/stream/beforeTemplate.worker.d.ts +1 -0
- package/dist/types/core/server/stream/shared.d.ts +1 -0
- package/dist/types/core/server/string/loadable.d.ts +1 -0
- 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
|
|
8
|
+
toggle: 'zobrazit hranice týmů'
|
|
7
9
|
},
|
|
8
10
|
en: {
|
|
9
|
-
toggle: 'show
|
|
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
|
|
21
|
+
const readStoredEnabled = (storageKey, fallback)=>{
|
|
20
22
|
if ("u" < typeof window) return fallback;
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
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
|
|
93
|
+
const toggleLabel = labels[language]?.toggle ?? labels.en?.toggle ?? defaultLabels.en?.toggle ?? 'show team boundaries';
|
|
46
94
|
useEffect(()=>{
|
|
47
95
|
setMounted(true);
|
|
48
|
-
|
|
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
|
-
|
|
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
|
|
65
|
-
|
|
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[
|
|
71
|
-
|
|
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:
|
|
75
|
-
label
|
|
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
|
|
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__*/
|
|
210
|
+
children: /*#__PURE__*/ jsxs("span", {
|
|
150
211
|
style: {
|
|
151
212
|
background: box.color,
|
|
152
213
|
borderRadius: 999,
|
|
153
214
|
color: '#111827',
|
|
154
|
-
|
|
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:
|
|
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
|
-
|
|
64
|
-
|
|
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,
|
|
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
|
|
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.
|