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