@bleedingdev/modern-js-runtime 3.9.0-ultramodern.2 → 3.9.0-ultramodern.21
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/cli/code.js +3 -1
- package/dist/cjs/cli/ssr/index.js +2 -74
- package/dist/cjs/cli/ssr/loadable-bundler-plugin.js +2 -0
- package/dist/cjs/cli/template.server.js +1 -2
- package/dist/cjs/core/browser/hydrate.js +9 -10
- package/dist/cjs/core/browser/index.js +4 -5
- package/dist/cjs/core/context/index.js +12 -45
- package/dist/cjs/core/context/public.js +4 -7
- package/dist/cjs/core/context/runtime.js +10 -4
- package/dist/cjs/core/index.js +3 -3
- package/dist/cjs/core/plugin/index.js +2 -2
- package/dist/cjs/core/react/index.js +3 -3
- package/dist/cjs/core/react/wrapper.js +23 -67
- package/dist/cjs/core/server/helmet.js +5 -4
- package/dist/cjs/core/server/requestHandler.js +6 -7
- package/dist/cjs/core/server/requestResponse.js +4 -4
- package/dist/cjs/core/server/routerCleanup.js +2 -2
- package/dist/cjs/core/server/shared.js +171 -4
- package/dist/cjs/core/server/stream/afterTemplate.js +21 -16
- package/dist/cjs/core/server/stream/beforeTemplate.js +37 -28
- package/dist/cjs/core/server/stream/beforeTemplate.worker.js +30 -23
- package/dist/cjs/core/server/stream/createReadableStream.js +222 -125
- package/dist/cjs/core/server/stream/createReadableStream.worker.js +171 -90
- package/dist/cjs/core/server/stream/deferredScript.js +3 -3
- package/dist/cjs/core/server/stream/shared.js +6 -2
- package/dist/cjs/core/server/string/index.js +104 -66
- package/dist/cjs/core/server/string/loadable.js +38 -23
- package/dist/cjs/core/server/string/ssrData.js +5 -12
- package/dist/cjs/core/server/utils.js +1 -2
- package/dist/cjs/document/cli/index.js +14 -5
- package/dist/cjs/exports/head.js +7 -14
- package/dist/cjs/internal.js +2 -2
- package/dist/cjs/router/cli/code/nestedRoutes.js +1 -2
- package/dist/cjs/router/cli/code/templates.js +1 -1
- package/dist/cjs/router/cli/code/utils.js +2 -2
- package/dist/cjs/router/runtime/DeferredDataScripts.node.js +10 -9
- package/dist/cjs/router/runtime/PrefetchLink.js +69 -125
- package/dist/cjs/router/runtime/hooks.js +13 -2
- package/dist/cjs/router/runtime/internal.js +7 -45
- package/dist/cjs/router/runtime/plugin.js +19 -34
- package/dist/cjs/router/runtime/plugin.node.js +9 -37
- package/dist/cjs/router/runtime/redirect.js +1 -1
- package/dist/esm/cli/code.mjs +3 -1
- package/dist/esm/cli/ssr/index.mjs +3 -72
- package/dist/esm/cli/ssr/loadable-bundler-plugin.mjs +2 -0
- package/dist/esm/cli/template.server.mjs +1 -2
- package/dist/esm/core/browser/hydrate.mjs +10 -11
- package/dist/esm/core/browser/index.mjs +1 -2
- package/dist/esm/core/context/index.mjs +2 -5
- package/dist/esm/core/context/public.mjs +1 -5
- package/dist/esm/core/context/runtime.mjs +6 -3
- package/dist/esm/core/index.mjs +1 -1
- package/dist/esm/core/plugin/index.mjs +1 -1
- package/dist/esm/core/react/index.mjs +1 -1
- package/dist/esm/core/react/wrapper.mjs +20 -67
- package/dist/esm/core/server/helmet.mjs +5 -4
- package/dist/esm/core/server/requestHandler.mjs +1 -2
- package/dist/esm/core/server/requestResponse.mjs +3 -3
- package/dist/esm/core/server/routerCleanup.mjs +1 -1
- package/dist/esm/core/server/shared.mjs +153 -1
- package/dist/esm/core/server/stream/afterTemplate.mjs +23 -18
- package/dist/esm/core/server/stream/beforeTemplate.mjs +40 -31
- package/dist/esm/core/server/stream/beforeTemplate.worker.mjs +33 -26
- package/dist/esm/core/server/stream/createReadableStream.mjs +220 -123
- package/dist/esm/core/server/stream/createReadableStream.worker.mjs +161 -90
- package/dist/esm/core/server/stream/deferredScript.mjs +3 -3
- package/dist/esm/core/server/stream/shared.mjs +4 -3
- package/dist/esm/core/server/string/index.mjs +106 -68
- package/dist/esm/core/server/string/loadable.mjs +38 -23
- package/dist/esm/core/server/string/ssrData.mjs +5 -12
- package/dist/esm/core/server/utils.mjs +1 -2
- package/dist/esm/document/cli/index.mjs +12 -6
- package/dist/esm/exports/head.mjs +7 -14
- package/dist/esm/internal.mjs +1 -1
- package/dist/esm/router/cli/code/nestedRoutes.mjs +1 -2
- package/dist/esm/router/cli/code/templates.mjs +1 -1
- package/dist/esm/router/cli/code/utils.mjs +2 -2
- package/dist/esm/router/runtime/DeferredDataScripts.node.mjs +10 -9
- package/dist/esm/router/runtime/PrefetchLink.mjs +68 -124
- package/dist/esm/router/runtime/hooks.mjs +9 -1
- package/dist/esm/router/runtime/internal.mjs +2 -33
- package/dist/esm/router/runtime/plugin.mjs +10 -25
- package/dist/esm/router/runtime/plugin.node.mjs +3 -31
- package/dist/esm/router/runtime/redirect.mjs +1 -1
- package/dist/esm-node/cli/code.mjs +3 -1
- package/dist/esm-node/cli/ssr/index.mjs +3 -72
- package/dist/esm-node/cli/ssr/loadable-bundler-plugin.mjs +2 -0
- package/dist/esm-node/cli/template.server.mjs +1 -2
- package/dist/esm-node/core/browser/hydrate.mjs +10 -11
- package/dist/esm-node/core/browser/index.mjs +1 -2
- package/dist/esm-node/core/context/index.mjs +2 -5
- package/dist/esm-node/core/context/public.mjs +1 -5
- package/dist/esm-node/core/context/runtime.mjs +6 -3
- package/dist/esm-node/core/index.mjs +1 -1
- package/dist/esm-node/core/plugin/index.mjs +1 -1
- package/dist/esm-node/core/react/index.mjs +1 -1
- package/dist/esm-node/core/react/wrapper.mjs +20 -67
- package/dist/esm-node/core/server/helmet.mjs +5 -4
- package/dist/esm-node/core/server/requestHandler.mjs +1 -2
- package/dist/esm-node/core/server/requestResponse.mjs +3 -3
- package/dist/esm-node/core/server/routerCleanup.mjs +1 -1
- package/dist/esm-node/core/server/shared.mjs +153 -1
- package/dist/esm-node/core/server/stream/afterTemplate.mjs +23 -18
- package/dist/esm-node/core/server/stream/beforeTemplate.mjs +40 -31
- package/dist/esm-node/core/server/stream/beforeTemplate.worker.mjs +33 -26
- package/dist/esm-node/core/server/stream/createReadableStream.mjs +220 -123
- package/dist/esm-node/core/server/stream/createReadableStream.worker.mjs +161 -90
- package/dist/esm-node/core/server/stream/deferredScript.mjs +3 -3
- package/dist/esm-node/core/server/stream/shared.mjs +4 -3
- package/dist/esm-node/core/server/string/index.mjs +106 -68
- package/dist/esm-node/core/server/string/loadable.mjs +38 -23
- package/dist/esm-node/core/server/string/ssrData.mjs +5 -12
- package/dist/esm-node/core/server/utils.mjs +1 -2
- package/dist/esm-node/document/cli/index.mjs +12 -6
- package/dist/esm-node/exports/head.mjs +7 -14
- package/dist/esm-node/internal.mjs +1 -1
- package/dist/esm-node/router/cli/code/nestedRoutes.mjs +1 -2
- package/dist/esm-node/router/cli/code/templates.mjs +1 -1
- package/dist/esm-node/router/cli/code/utils.mjs +2 -2
- package/dist/esm-node/router/runtime/DeferredDataScripts.node.mjs +10 -9
- package/dist/esm-node/router/runtime/PrefetchLink.mjs +68 -124
- package/dist/esm-node/router/runtime/hooks.mjs +9 -1
- package/dist/esm-node/router/runtime/internal.mjs +2 -33
- package/dist/esm-node/router/runtime/plugin.mjs +10 -25
- package/dist/esm-node/router/runtime/plugin.node.mjs +3 -31
- package/dist/esm-node/router/runtime/redirect.mjs +1 -1
- package/dist/types/cli/ssr/index.d.ts +0 -3
- package/dist/types/core/context/index.d.ts +4 -6
- package/dist/types/core/context/public.d.ts +1 -23
- package/dist/types/core/context/runtime.d.ts +26 -2
- package/dist/types/core/index.d.ts +1 -1
- package/dist/types/core/react/wrapper.d.ts +7 -1
- package/dist/types/core/server/helmet.d.ts +4 -5
- package/dist/types/core/server/requestHandler.d.ts +3 -3
- package/dist/types/core/server/requestResponse.d.ts +1 -1
- package/dist/types/core/server/routerCleanup.d.ts +1 -1
- package/dist/types/core/server/shared.d.ts +24 -1
- package/dist/types/core/server/stream/afterTemplate.d.ts +2 -1
- package/dist/types/core/server/stream/beforeTemplate.d.ts +4 -1
- package/dist/types/core/server/stream/beforeTemplate.worker.d.ts +4 -1
- package/dist/types/core/server/stream/shared.d.ts +16 -2
- package/dist/types/core/server/string/loadable.d.ts +6 -3
- package/dist/types/core/server/string/ssrData.d.ts +2 -1
- package/dist/types/core/server/string/types.d.ts +1 -5
- package/dist/types/core/server/tracer.d.ts +1 -1
- package/dist/types/core/server/utils.d.ts +1 -1
- package/dist/types/core/types.d.ts +1 -2
- package/dist/types/document/cli/index.d.ts +1 -0
- package/dist/types/exports/head.d.ts +2 -2
- package/dist/types/internal.d.ts +1 -1
- package/dist/types/router/runtime/PrefetchLink.d.ts +27 -2
- package/dist/types/router/runtime/hooks.d.ts +19 -2
- package/dist/types/router/runtime/internal.d.ts +4 -21
- package/dist/types/router/runtime/types.d.ts +2 -43
- package/package.json +18 -46
- package/rslib.config.mts +3 -0
- package/rstest.config.mts +28 -2
- package/dist/cjs/boundary-debugger/index.js +0 -317
- package/dist/cjs/core/context/extensions.js +0 -74
- package/dist/cjs/core/context/helmetContext.js +0 -54
- package/dist/cjs/core/server/federatedCss.js +0 -58
- package/dist/cjs/core/server/scriptOrder.js +0 -140
- package/dist/cjs/module-federation/consume-surface.js +0 -199
- package/dist/cjs/module-federation/distributed-ssr.js +0 -135
- package/dist/cjs/module-federation/index.js +0 -316
- package/dist/cjs/module-federation/last-known-good.js +0 -157
- package/dist/cjs/module-federation/manifest-recovery-runtime-plugin.js +0 -129
- package/dist/cjs/module-federation/surface-resolution-types.js +0 -61
- package/dist/cjs/router/runtime/lifecycle.js +0 -167
- package/dist/cjs/router/runtime/provider.js +0 -153
- package/dist/cjs/rsc/server.worker.js +0 -62
- package/dist/esm/boundary-debugger/index.mjs +0 -277
- package/dist/esm/core/context/extensions.mjs +0 -33
- package/dist/esm/core/context/helmetContext.mjs +0 -13
- package/dist/esm/core/server/federatedCss.mjs +0 -20
- package/dist/esm/core/server/scriptOrder.mjs +0 -90
- package/dist/esm/module-federation/consume-surface.mjs +0 -158
- package/dist/esm/module-federation/distributed-ssr.mjs +0 -82
- package/dist/esm/module-federation/index.mjs +0 -115
- package/dist/esm/module-federation/last-known-good.mjs +0 -113
- package/dist/esm/module-federation/manifest-recovery-runtime-plugin.mjs +0 -89
- package/dist/esm/module-federation/surface-resolution-types.mjs +0 -8
- package/dist/esm/router/runtime/lifecycle.mjs +0 -105
- package/dist/esm/router/runtime/provider.mjs +0 -100
- package/dist/esm/rsc/server.worker.mjs +0 -1
- package/dist/esm-node/boundary-debugger/index.mjs +0 -278
- package/dist/esm-node/core/context/extensions.mjs +0 -34
- package/dist/esm-node/core/context/helmetContext.mjs +0 -14
- package/dist/esm-node/core/server/federatedCss.mjs +0 -21
- package/dist/esm-node/core/server/scriptOrder.mjs +0 -91
- package/dist/esm-node/module-federation/consume-surface.mjs +0 -159
- package/dist/esm-node/module-federation/distributed-ssr.mjs +0 -83
- package/dist/esm-node/module-federation/index.mjs +0 -116
- package/dist/esm-node/module-federation/last-known-good.mjs +0 -114
- package/dist/esm-node/module-federation/manifest-recovery-runtime-plugin.mjs +0 -90
- package/dist/esm-node/module-federation/surface-resolution-types.mjs +0 -9
- package/dist/esm-node/router/runtime/lifecycle.mjs +0 -106
- package/dist/esm-node/router/runtime/provider.mjs +0 -101
- package/dist/esm-node/rsc/server.worker.mjs +0 -2
- package/dist/types/boundary-debugger/index.d.ts +0 -28
- package/dist/types/core/context/extensions.d.ts +0 -35
- package/dist/types/core/context/helmetContext.d.ts +0 -10
- package/dist/types/core/server/federatedCss.d.ts +0 -5
- package/dist/types/core/server/scriptOrder.d.ts +0 -25
- package/dist/types/module-federation/consume-surface.d.ts +0 -104
- package/dist/types/module-federation/distributed-ssr.d.ts +0 -61
- package/dist/types/module-federation/index.d.ts +0 -71
- package/dist/types/module-federation/last-known-good.d.ts +0 -52
- package/dist/types/module-federation/manifest-recovery-runtime-plugin.d.ts +0 -25
- package/dist/types/module-federation/surface-resolution-types.d.ts +0 -23
- package/dist/types/router/runtime/lifecycle.d.ts +0 -27
- package/dist/types/router/runtime/provider.d.ts +0 -78
- package/dist/types/rsc/server.worker.d.ts +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { getGlobalApp, getGlobalInternalRuntimeContext } from "@modern-js/runtime/context";
|
|
1
2
|
import { parsedJSONFromElement } from "@modern-js/runtime-utils/parsed";
|
|
2
3
|
import { isBrowser } from "../../common.mjs";
|
|
3
4
|
import { ROUTER_DATA_JSON_ID, SSR_DATA_JSON_ID } from "../constants.mjs";
|
|
4
|
-
import { getGlobalApp, getGlobalInternalRuntimeContext } from "../context/index.mjs";
|
|
5
5
|
function createRoot(UserApp) {
|
|
6
6
|
const App = UserApp || getGlobalApp();
|
|
7
7
|
if (isBrowser()) {
|
|
@@ -1,45 +1,13 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const requestContext = getInitialContext().requestContext;
|
|
8
|
-
Object.defineProperty(requestContext.response, 'setHeader', {
|
|
9
|
-
enumerable: false
|
|
2
|
+
import { InternalRuntimeContext, RuntimeComponentResolverContext, RuntimeContext, getGlobalEnableRsc, getGlobalInternalRuntimeContext } from "@modern-js/runtime/context";
|
|
3
|
+
function wrapRuntimeComponentResolver(root, hooks = getGlobalInternalRuntimeContext()?.hooks) {
|
|
4
|
+
return /*#__PURE__*/ jsx(RuntimeComponentResolverContext.Provider, {
|
|
5
|
+
value: hooks?.resolveComponent?.call,
|
|
6
|
+
children: root
|
|
10
7
|
});
|
|
11
|
-
Object.defineProperty(requestContext.response, 'status', {
|
|
12
|
-
enumerable: false
|
|
13
|
-
});
|
|
14
|
-
if (void 0 === ssrContext) return requestContext;
|
|
15
|
-
const { request, response } = ssrContext;
|
|
16
|
-
return {
|
|
17
|
-
request: {
|
|
18
|
-
url: request.url,
|
|
19
|
-
userAgent: request.userAgent,
|
|
20
|
-
cookie: request.cookie,
|
|
21
|
-
pathname: request.pathname,
|
|
22
|
-
query: {
|
|
23
|
-
...request.query
|
|
24
|
-
},
|
|
25
|
-
params: {
|
|
26
|
-
...request.params
|
|
27
|
-
},
|
|
28
|
-
headers: {
|
|
29
|
-
...request.headers
|
|
30
|
-
},
|
|
31
|
-
host: request.host,
|
|
32
|
-
referer: request.referer
|
|
33
|
-
},
|
|
34
|
-
response: Object.assign(requestContext.response, {
|
|
35
|
-
locals: response.locals ?? {}
|
|
36
|
-
})
|
|
37
|
-
};
|
|
38
8
|
}
|
|
39
9
|
function wrapRuntimeContextProvider(App, contextValue) {
|
|
40
10
|
const { isBrowser, initialData, routes, context, routeManifest, routerContext, unstable_getBlockNavState, ssrContext, _internalContext, _internalRouterBaseName, ...rest } = contextValue;
|
|
41
|
-
const internalContextValue = contextValue;
|
|
42
|
-
const helmetContext = ensureHelmetContext(internalContextValue);
|
|
43
11
|
const runtimeContextValue = {
|
|
44
12
|
isBrowser,
|
|
45
13
|
initialData,
|
|
@@ -47,37 +15,22 @@ function wrapRuntimeContextProvider(App, contextValue) {
|
|
|
47
15
|
context,
|
|
48
16
|
...rest
|
|
49
17
|
};
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
context: rscSafeRequestContext,
|
|
62
|
-
requestContext: rscSafeRequestContext
|
|
63
|
-
};
|
|
64
|
-
return /*#__PURE__*/ jsx(InternalRuntimeContext.Provider, {
|
|
65
|
-
value: rscInternalContextValue,
|
|
66
|
-
children: /*#__PURE__*/ jsx(RuntimeContext.Provider, {
|
|
67
|
-
value: rscRuntimeContextValue,
|
|
68
|
-
children: App
|
|
69
|
-
})
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
return /*#__PURE__*/ jsx(InternalRuntimeContext.Provider, {
|
|
73
|
-
value: internalContextValue,
|
|
18
|
+
const isRsc = true === getGlobalEnableRsc();
|
|
19
|
+
const projection = {
|
|
20
|
+
internalContext: contextValue,
|
|
21
|
+
publicContext: runtimeContextValue
|
|
22
|
+
};
|
|
23
|
+
const values = getGlobalInternalRuntimeContext()?.hooks.transformRuntimeContext?.call(projection, {
|
|
24
|
+
context: contextValue,
|
|
25
|
+
isRsc
|
|
26
|
+
}) ?? projection;
|
|
27
|
+
const root = /*#__PURE__*/ jsx(InternalRuntimeContext.Provider, {
|
|
28
|
+
value: values.internalContext,
|
|
74
29
|
children: /*#__PURE__*/ jsx(RuntimeContext.Provider, {
|
|
75
|
-
value:
|
|
76
|
-
children:
|
|
77
|
-
context: helmetContext,
|
|
78
|
-
children: App
|
|
79
|
-
})
|
|
30
|
+
value: values.publicContext,
|
|
31
|
+
children: App
|
|
80
32
|
})
|
|
81
33
|
});
|
|
34
|
+
return isRsc && false === isBrowser ? root : wrapRuntimeComponentResolver(root);
|
|
82
35
|
}
|
|
83
|
-
export { wrapRuntimeContextProvider };
|
|
36
|
+
export { wrapRuntimeComponentResolver, wrapRuntimeContextProvider };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { getHelmetContext } from "../context/helmetContext.mjs";
|
|
2
1
|
import { safeReplace } from "./utils.mjs";
|
|
3
2
|
const EOL = '\n';
|
|
4
3
|
const RE_HTML_ATTR = /<html[^>]*>/;
|
|
@@ -6,8 +5,10 @@ const RE_BODY_ATTR = /<body[^>]*>/;
|
|
|
6
5
|
const RE_LAST_IN_HEAD = /<\/head>/;
|
|
7
6
|
const RE_TITLE = /<title[^>]*>([\s\S\n\r]*?)<\/title>/;
|
|
8
7
|
const TEST_TITLE_CONTENT = /(?<=<title[^>]*>)([\s\S\n\r]*?)([.|\S])([\s\S\n\r]*?)(?=<\/title>)/;
|
|
9
|
-
function getHelmetData(
|
|
10
|
-
|
|
8
|
+
function getHelmetData(providers) {
|
|
9
|
+
let result;
|
|
10
|
+
for (const provider of providers)result = provider.getHeadData?.() ?? result;
|
|
11
|
+
return result;
|
|
11
12
|
}
|
|
12
13
|
function createReplaceHelemt(helmetData) {
|
|
13
14
|
return helmetData ? (template)=>helmetReplace(template, helmetData) : (tempalte)=>tempalte;
|
|
@@ -19,7 +20,7 @@ function helmetReplace(content, helmetData) {
|
|
|
19
20
|
const htmlAttributes = helmetData.htmlAttributes.toString();
|
|
20
21
|
if (htmlAttributes) result = safeReplace(result, RE_HTML_ATTR, `<html ${htmlAttributes}>`);
|
|
21
22
|
const base = helmetData.base.toString();
|
|
22
|
-
const priority = helmetData.priority
|
|
23
|
+
const priority = helmetData.priority?.toString() ?? '';
|
|
23
24
|
const link = helmetData.link.toString();
|
|
24
25
|
const meta = helmetData.meta.toString();
|
|
25
26
|
const noscript = helmetData.noscript.toString();
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { getGlobalInternalRuntimeContext, getGlobalRSCRoot, getInitialContext } from "@modern-js/runtime/context";
|
|
2
3
|
import { storage } from "@modern-js/runtime-utils/node";
|
|
3
4
|
import { getPathname, parseCookie, parseHeaders, parseQuery } from "@modern-js/runtime-utils/universal/request";
|
|
4
5
|
import react, { Fragment } from "react";
|
|
5
|
-
import { getGlobalInternalRuntimeContext, getGlobalRSCRoot } from "../context/index.mjs";
|
|
6
|
-
import { getInitialContext } from "../context/runtime.mjs";
|
|
7
6
|
import { getServerPayload } from "../context/serverPayload/index.mjs";
|
|
8
7
|
import { createRoot } from "../react/index.mjs";
|
|
9
8
|
import { CHUNK_CSS_PLACEHOLDER } from "./constants.mjs";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { getRouterServerSnapshot } from "
|
|
1
|
+
import { getRouterServerSnapshot } from "@modern-js/runtime-extensions/router-state";
|
|
2
2
|
import { handleRSCRedirect } from "../../router/runtime/redirect.mjs";
|
|
3
3
|
import { SSRErrors } from "./tracer.mjs";
|
|
4
4
|
const isRedirectStatus = (status)=>301 === status || 302 === status || 303 === status || 307 === status || 308 === status;
|
|
5
5
|
const isNullBodyStatus = (status)=>204 === status || 205 === status || 304 === status;
|
|
6
6
|
const getRedirectLocation = (headers)=>{
|
|
7
7
|
const location = headers.get('Location');
|
|
8
|
-
return location && URL.canParse(location, 'http://localhost') ? location : void 0;
|
|
8
|
+
return null !== location && '' !== location && URL.canParse(location, 'http://localhost') ? location : void 0;
|
|
9
9
|
};
|
|
10
10
|
const processRedirect = (headers, status, ctx)=>{
|
|
11
11
|
headers.delete('content-length');
|
|
@@ -27,7 +27,7 @@ const createLoaderRedirectResponse = (beforeRenderResult, redirectCtx)=>{
|
|
|
27
27
|
if (void 0 === beforeRenderResult || !isRedirectStatus(beforeRenderResult.status)) return;
|
|
28
28
|
if (beforeRenderResult.headers.has('X-Modernjs-Redirect')) return beforeRenderResult;
|
|
29
29
|
const redirectUrl = getRedirectLocation(beforeRenderResult.headers);
|
|
30
|
-
if (
|
|
30
|
+
if (void 0 === redirectUrl) return;
|
|
31
31
|
return processRedirect(new Headers(beforeRenderResult.headers), beforeRenderResult.status, redirectCtx);
|
|
32
32
|
};
|
|
33
33
|
const finalizeRenderResponse = async (response, responseProxy, redirectCtx, routerCleanup)=>{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getRouterRuntimeState } from "
|
|
1
|
+
import { getRouterRuntimeState } from "@modern-js/runtime-extensions/router-state";
|
|
2
2
|
const ROUTER_CLEANUP_ERROR = 'An error occurs during router runtime cleanup';
|
|
3
3
|
async function runWithRouterCleanupOnError(routerCleanup, callback) {
|
|
4
4
|
try {
|
|
@@ -1,4 +1,156 @@
|
|
|
1
|
+
import { attributesToString, hasStylesheetLink, safeReplace } from "./utils.mjs";
|
|
1
2
|
function buildHtml(template, callbacks) {
|
|
2
3
|
return callbacks.reduce((promise, buildHtmlCb)=>promise.then((template)=>buildHtmlCb(template)), Promise.resolve(template));
|
|
3
4
|
}
|
|
4
|
-
|
|
5
|
+
function createSSRRenderLifecycle(observers) {
|
|
6
|
+
let terminal;
|
|
7
|
+
return {
|
|
8
|
+
transformAssets (groups, info) {
|
|
9
|
+
let assets = groups.flatMap((group)=>group.assets);
|
|
10
|
+
for (const observer of observers)assets = observer.transformAssets?.(assets, {
|
|
11
|
+
...info,
|
|
12
|
+
groups
|
|
13
|
+
}) ?? assets;
|
|
14
|
+
return assets;
|
|
15
|
+
},
|
|
16
|
+
transformTemplateChunk (chunk) {
|
|
17
|
+
for (const observer of observers)chunk = observer.transformTemplateChunk?.(chunk, {
|
|
18
|
+
attributesToString: attributesToString,
|
|
19
|
+
hasStylesheetLink: hasStylesheetLink
|
|
20
|
+
}) ?? chunk;
|
|
21
|
+
return chunk;
|
|
22
|
+
},
|
|
23
|
+
getRouterData () {
|
|
24
|
+
let data;
|
|
25
|
+
for (const observer of observers)data = observer.getRouterData?.() ?? data;
|
|
26
|
+
return data;
|
|
27
|
+
},
|
|
28
|
+
get terminal () {
|
|
29
|
+
return terminal;
|
|
30
|
+
},
|
|
31
|
+
beforeReact () {
|
|
32
|
+
for (const observer of observers)observer.beforeReact?.();
|
|
33
|
+
},
|
|
34
|
+
completedBody (html, phase) {
|
|
35
|
+
for (const observer of observers)html = observer.completedBody?.(html, {
|
|
36
|
+
phase
|
|
37
|
+
}) ?? html;
|
|
38
|
+
return html;
|
|
39
|
+
},
|
|
40
|
+
finish (result) {
|
|
41
|
+
if (void 0 !== terminal) return;
|
|
42
|
+
terminal = result;
|
|
43
|
+
for (const observer of observers)try {
|
|
44
|
+
observer.onTerminal?.(result);
|
|
45
|
+
} catch {}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function replaceSSRTemplateChunk(chunk, lifecycle, options = {}) {
|
|
50
|
+
const result = lifecycle?.transformTemplateChunk(chunk) ?? chunk;
|
|
51
|
+
if (true === options.preserveEmpty && '' === result.content) return result.template;
|
|
52
|
+
return safeReplace(result.template, result.placeholder, result.content);
|
|
53
|
+
}
|
|
54
|
+
function orderSSRStreamTransforms(extenders) {
|
|
55
|
+
return [
|
|
56
|
+
...extenders.filter((extender)=>'body' !== extender.streamPhase),
|
|
57
|
+
...extenders.filter((extender)=>'body' === extender.streamPhase)
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
function createSSRStreamErrorReporter(onError) {
|
|
61
|
+
let reported = false;
|
|
62
|
+
return (error)=>{
|
|
63
|
+
if (reported) return;
|
|
64
|
+
reported = true;
|
|
65
|
+
try {
|
|
66
|
+
onError(error);
|
|
67
|
+
} catch {}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function observeSSRStream(source, options) {
|
|
71
|
+
const reader = source.getReader();
|
|
72
|
+
let controller;
|
|
73
|
+
let ended = false;
|
|
74
|
+
let cancellation;
|
|
75
|
+
const cleanup = ()=>{
|
|
76
|
+
options.signal.removeEventListener('abort', onAbort);
|
|
77
|
+
reader.releaseLock();
|
|
78
|
+
};
|
|
79
|
+
const cancel = (reason)=>{
|
|
80
|
+
if (void 0 !== cancellation) return cancellation;
|
|
81
|
+
if (ended) return Promise.resolve();
|
|
82
|
+
ended = true;
|
|
83
|
+
options.lifecycle.finish({
|
|
84
|
+
status: 'cancelled',
|
|
85
|
+
reason
|
|
86
|
+
});
|
|
87
|
+
cancellation = (async ()=>{
|
|
88
|
+
try {
|
|
89
|
+
const observer = Promise.withResolvers();
|
|
90
|
+
try {
|
|
91
|
+
observer.resolve(options.onCancel?.(reason));
|
|
92
|
+
} catch (error) {
|
|
93
|
+
observer.reject(error);
|
|
94
|
+
}
|
|
95
|
+
const results = await Promise.allSettled([
|
|
96
|
+
observer.promise,
|
|
97
|
+
reader.cancel(reason)
|
|
98
|
+
]);
|
|
99
|
+
const rejected = results.find((result)=>'rejected' === result.status);
|
|
100
|
+
if (rejected?.status === 'rejected') throw rejected.reason;
|
|
101
|
+
} finally{
|
|
102
|
+
cleanup();
|
|
103
|
+
}
|
|
104
|
+
})();
|
|
105
|
+
return cancellation;
|
|
106
|
+
};
|
|
107
|
+
const onAbort = ()=>{
|
|
108
|
+
if (ended) return;
|
|
109
|
+
const reason = options.signal.reason;
|
|
110
|
+
cancel(reason).then(()=>controller.error(reason), (error)=>{
|
|
111
|
+
controller.error(reason);
|
|
112
|
+
return options.onError(error);
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
return new ReadableStream({
|
|
116
|
+
start (value) {
|
|
117
|
+
controller = value;
|
|
118
|
+
options.signal.addEventListener('abort', onAbort, {
|
|
119
|
+
once: true
|
|
120
|
+
});
|
|
121
|
+
if (options.signal.aborted) onAbort();
|
|
122
|
+
},
|
|
123
|
+
async pull (value) {
|
|
124
|
+
if (ended) return void await cancellation;
|
|
125
|
+
try {
|
|
126
|
+
const result = await reader.read();
|
|
127
|
+
if (ended) return void await cancellation;
|
|
128
|
+
if (result.done) {
|
|
129
|
+
await options.onComplete?.();
|
|
130
|
+
if (ended) return void await cancellation;
|
|
131
|
+
ended = true;
|
|
132
|
+
options.lifecycle.finish({
|
|
133
|
+
status: 'complete'
|
|
134
|
+
});
|
|
135
|
+
cleanup();
|
|
136
|
+
value.close();
|
|
137
|
+
} else value.enqueue(result.value);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
if (ended) return void await cancellation;
|
|
140
|
+
ended = true;
|
|
141
|
+
options.lifecycle.finish({
|
|
142
|
+
status: 'error',
|
|
143
|
+
error
|
|
144
|
+
});
|
|
145
|
+
try {
|
|
146
|
+
await options.onError(error);
|
|
147
|
+
} finally{
|
|
148
|
+
cleanup();
|
|
149
|
+
value.error(error);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
cancel
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
export { buildHtml, createSSRRenderLifecycle, createSSRStreamErrorReporter, observeSSRStream, orderSSRStreamTransforms, replaceSSRTemplateChunk };
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { serializeJson } from "@modern-js/runtime-utils/node";
|
|
2
|
-
import { getRouterHydrationScripts } from "../../../router/runtime/lifecycle.mjs";
|
|
3
2
|
import { SSR_DATA_JSON_ID } from "../../constants.mjs";
|
|
4
|
-
import { SSR_DATA_PLACEHOLDER } from "../constants.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import { buildHtml } from "../shared.mjs";
|
|
3
|
+
import { CHUNK_JS_PLACEHOLDER, SSR_DATA_PLACEHOLDER } from "../constants.mjs";
|
|
4
|
+
import { buildHtml, replaceSSRTemplateChunk } from "../shared.mjs";
|
|
7
5
|
import { attributesToString } from "../utils.mjs";
|
|
8
6
|
function buildShellAfterTemplate(afterAppTemplate, options) {
|
|
9
|
-
const { request, config, ssrConfig, runtimeContext, renderLevel, entryName } = options;
|
|
7
|
+
const { request, config, ssrConfig, runtimeContext, renderLevel, entryName, lifecycle } = options;
|
|
10
8
|
const callbacks = [
|
|
11
9
|
(template)=>injectJs(template, entryName, config.nonce),
|
|
12
10
|
createReplaceSSRData({
|
|
@@ -16,21 +14,28 @@ function buildShellAfterTemplate(afterAppTemplate, options) {
|
|
|
16
14
|
useJsonScript: config.useJsonScript,
|
|
17
15
|
runtimeContext,
|
|
18
16
|
renderLevel,
|
|
19
|
-
|
|
17
|
+
lifecycle
|
|
20
18
|
})
|
|
21
19
|
];
|
|
22
20
|
async function injectJs(template, entryName, nonce) {
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
const assets = runtimeContext.routeManifest?.routeAssets?.[`async-${entryName}`]?.assets ?? [];
|
|
22
|
+
const jsChunkStr = assets.filter((asset)=>asset.endsWith('.js')).map((asset)=>`<script${attributesToString({
|
|
23
|
+
src: asset,
|
|
24
|
+
nonce
|
|
25
|
+
})}></script>`).join(' ');
|
|
26
|
+
return replaceSSRTemplateChunk({
|
|
27
|
+
name: "scripts",
|
|
28
|
+
template,
|
|
29
|
+
placeholder: CHUNK_JS_PLACEHOLDER,
|
|
30
|
+
content: jsChunkStr
|
|
31
|
+
}, lifecycle, {
|
|
32
|
+
preserveEmpty: true
|
|
26
33
|
});
|
|
27
|
-
if (!jsChunkStr) return template;
|
|
28
|
-
return replaceChunkJsPlaceholder(template, jsChunkStr, entryName);
|
|
29
34
|
}
|
|
30
35
|
return buildHtml(afterAppTemplate, callbacks);
|
|
31
36
|
}
|
|
32
37
|
function createReplaceSSRData(options) {
|
|
33
|
-
const { runtimeContext, nonce, renderLevel, useJsonScript, ssrConfig,
|
|
38
|
+
const { runtimeContext, nonce, renderLevel, useJsonScript, ssrConfig, lifecycle } = options;
|
|
34
39
|
const { request, reporter } = runtimeContext.ssrContext;
|
|
35
40
|
const headers = 'object' == typeof ssrConfig && ssrConfig.unsafeHeaders ? Object.fromEntries(Object.entries(request.headers).filter(([key, _])=>ssrConfig.unsafeHeaders?.map((header)=>header.toLowerCase())?.includes(key.toLowerCase()))) : void 0;
|
|
36
41
|
const ssrData = {
|
|
@@ -59,11 +64,11 @@ function createReplaceSSRData(options) {
|
|
|
59
64
|
});
|
|
60
65
|
const serializeSSRData = serializeJson(ssrData);
|
|
61
66
|
const ssrDataScript = useJsonScript ? `<script type="application/json" id="${SSR_DATA_JSON_ID}">${serializeSSRData}</script>` : `<script${attrsStr}>window._SSR_DATA = ${serializeSSRData}</script>`;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
return (template)=>replaceSSRTemplateChunk({
|
|
68
|
+
name: 'data',
|
|
69
|
+
template,
|
|
70
|
+
placeholder: SSR_DATA_PLACEHOLDER,
|
|
71
|
+
content: ssrDataScript
|
|
72
|
+
}, lifecycle);
|
|
68
73
|
}
|
|
69
74
|
export { buildShellAfterTemplate };
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { matchRoutes } from "@modern-js/runtime-utils/router";
|
|
2
|
-
import { getRouterMatchedRouteIds } from "../../../router/runtime/lifecycle.mjs";
|
|
3
2
|
import { CHUNK_CSS_PLACEHOLDER } from "../constants.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { checkIsNode, hasStylesheetLink, safeReplace } from "../utils.mjs";
|
|
3
|
+
import { createReplaceHelemt } from "../helmet.mjs";
|
|
4
|
+
import { buildHtml, replaceSSRTemplateChunk } from "../shared.mjs";
|
|
5
|
+
import { checkIsNode, hasStylesheetLink } from "../utils.mjs";
|
|
8
6
|
const readAsset = async (chunk)=>{
|
|
9
7
|
const fs = await import("fs/promises");
|
|
10
8
|
const path = await import("path");
|
|
@@ -13,12 +11,11 @@ const readAsset = async (chunk)=>{
|
|
|
13
11
|
};
|
|
14
12
|
const checkIsInline = (chunk, enableInline)=>{
|
|
15
13
|
if ('production' !== process.env.NODE_ENV) return false;
|
|
16
|
-
if (enableInline instanceof RegExp) return enableInline.test(chunk);
|
|
17
|
-
return Boolean(enableInline);
|
|
14
|
+
else if (enableInline instanceof RegExp) return enableInline.test(chunk);
|
|
15
|
+
else return Boolean(enableInline);
|
|
18
16
|
};
|
|
19
17
|
async function buildShellBeforeTemplate(beforeAppTemplate, options) {
|
|
20
|
-
const { config, runtimeContext, styledComponentsStyleTags, entryName,
|
|
21
|
-
const helmetData = getHelmetData(runtimeContext);
|
|
18
|
+
const { config, runtimeContext, styledComponentsStyleTags, entryName, lifecycle, helmetData } = options;
|
|
22
19
|
const callbacks = [
|
|
23
20
|
createReplaceHelemt(helmetData),
|
|
24
21
|
(template)=>injectCss(template, entryName, styledComponentsStyleTags)
|
|
@@ -27,41 +24,53 @@ async function buildShellBeforeTemplate(beforeAppTemplate, options) {
|
|
|
27
24
|
async function injectCss(template, entryName, styledComponentsStyleTags) {
|
|
28
25
|
let css = await getCssChunks();
|
|
29
26
|
if (styledComponentsStyleTags) css += styledComponentsStyleTags;
|
|
30
|
-
|
|
27
|
+
return replaceSSRTemplateChunk({
|
|
28
|
+
name: 'styles',
|
|
31
29
|
template,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
placeholder: CHUNK_CSS_PLACEHOLDER,
|
|
31
|
+
content: css,
|
|
32
|
+
emittedAssets: css.match(/href="([^"]+)"/g)?.map((item)=>item.replace(/^href="/, '').replace(/"$/, ''))
|
|
33
|
+
}, lifecycle);
|
|
35
34
|
async function getCssChunks() {
|
|
36
35
|
const { routeManifest, routerContext, routes } = runtimeContext;
|
|
37
36
|
const routeAssets = routeManifest?.routeAssets;
|
|
38
37
|
if (!routeAssets) return '';
|
|
39
38
|
let matchedRouteManifests = [];
|
|
40
|
-
|
|
41
|
-
if (matchedRouteIds?.length) matchedRouteManifests = matchedRouteIds.map((routeId)=>routeAssets[routeId]).filter(Boolean);
|
|
42
|
-
else if (routerContext && routes) {
|
|
39
|
+
if (routerContext && routes) {
|
|
43
40
|
const matches = matchRoutes(routes, routerContext.location, routerContext.basename);
|
|
44
|
-
matchedRouteManifests = matches?.
|
|
45
|
-
if (!index) return;
|
|
41
|
+
matchedRouteManifests = matches?.flatMap((match, index)=>{
|
|
46
42
|
const routeId = match.route.id;
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
const manifest = 0 !== index && routeId ? routeAssets[routeId] : void 0;
|
|
44
|
+
return void 0 === manifest ? [] : [
|
|
45
|
+
manifest
|
|
46
|
+
];
|
|
47
|
+
}) ?? [];
|
|
49
48
|
}
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
const createAsset = (url)=>({
|
|
50
|
+
url
|
|
51
|
+
});
|
|
52
|
+
const groups = [
|
|
53
|
+
{
|
|
54
|
+
name: 'route',
|
|
55
|
+
assets: matchedRouteManifests.flatMap((manifest)=>manifest.referenceCssAssets ?? []).map(createAsset)
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'async-entry',
|
|
59
|
+
assets: (routeAssets[`async-${entryName}`]?.referenceCssAssets ?? []).map(createAsset)
|
|
60
|
+
}
|
|
61
|
+
];
|
|
62
|
+
const assets = lifecycle?.transformAssets(groups, {
|
|
63
|
+
kind: 'style',
|
|
64
|
+
source: 'template',
|
|
65
|
+
template,
|
|
66
|
+
createAsset
|
|
67
|
+
}) ?? groups.flatMap((group)=>group.assets);
|
|
68
|
+
const cssChunks = assets.map((asset)=>asset.url).filter((asset)=>asset.endsWith('.css') && !hasStylesheetLink(template, asset));
|
|
60
69
|
const { inlineStyles } = config;
|
|
61
70
|
const styles = await Promise.all(cssChunks.map(async (chunk)=>{
|
|
62
71
|
const link = `<link href="${chunk}" rel="stylesheet" />`;
|
|
63
72
|
if (checkIsNode() && checkIsInline(chunk, inlineStyles)) return readAsset(chunk).then((content)=>`<style>${content}</style>`).catch((_)=>link);
|
|
64
|
-
return link;
|
|
73
|
+
else return link;
|
|
65
74
|
}));
|
|
66
75
|
return `${styles.join('')}`;
|
|
67
76
|
}
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
import { getRouterMatchedRouteIds } from "../../../router/runtime/lifecycle.mjs";
|
|
2
1
|
import { CHUNK_CSS_PLACEHOLDER } from "../constants.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { hasStylesheetLink, safeReplace } from "../utils.mjs";
|
|
2
|
+
import { createReplaceHelemt } from "../helmet.mjs";
|
|
3
|
+
import { buildHtml, replaceSSRTemplateChunk } from "../shared.mjs";
|
|
4
|
+
import { hasStylesheetLink } from "../utils.mjs";
|
|
7
5
|
const checkIsInline = (chunk, enableInline)=>{
|
|
8
6
|
if ('production' !== process.env.NODE_ENV) return false;
|
|
9
|
-
if (enableInline instanceof RegExp) return enableInline.test(chunk);
|
|
10
|
-
return Boolean(enableInline);
|
|
7
|
+
else if (enableInline instanceof RegExp) return enableInline.test(chunk);
|
|
8
|
+
else return Boolean(enableInline);
|
|
11
9
|
};
|
|
12
10
|
async function buildShellBeforeTemplate(beforeAppTemplate, options) {
|
|
13
|
-
const { config, runtimeContext, styledComponentsStyleTags, entryName,
|
|
14
|
-
const helmetData = getHelmetData(runtimeContext);
|
|
11
|
+
const { config, runtimeContext, styledComponentsStyleTags, entryName, lifecycle, helmetData } = options;
|
|
15
12
|
const callbacks = [
|
|
16
13
|
createReplaceHelemt(helmetData),
|
|
17
14
|
(template)=>injectCss(template, entryName, styledComponentsStyleTags)
|
|
@@ -20,28 +17,38 @@ async function buildShellBeforeTemplate(beforeAppTemplate, options) {
|
|
|
20
17
|
async function injectCss(template, entryName, styledComponentsStyleTags) {
|
|
21
18
|
let css = await getCssChunks();
|
|
22
19
|
if (styledComponentsStyleTags) css += styledComponentsStyleTags;
|
|
23
|
-
|
|
20
|
+
return replaceSSRTemplateChunk({
|
|
21
|
+
name: 'styles',
|
|
24
22
|
template,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
placeholder: CHUNK_CSS_PLACEHOLDER,
|
|
24
|
+
content: css,
|
|
25
|
+
emittedAssets: css.match(/href="([^"]+)"/g)?.map((item)=>item.replace(/^href="/, '').replace(/"$/, ''))
|
|
26
|
+
}, lifecycle);
|
|
28
27
|
async function getCssChunks() {
|
|
29
28
|
const { routeManifest } = runtimeContext;
|
|
30
29
|
const routeAssets = routeManifest?.routeAssets;
|
|
31
30
|
if (!routeAssets) return '';
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
const matchedRouteManifests = [];
|
|
32
|
+
const createAsset = (url)=>({
|
|
33
|
+
url
|
|
34
|
+
});
|
|
35
|
+
const groups = [
|
|
36
|
+
{
|
|
37
|
+
name: 'route',
|
|
38
|
+
assets: matchedRouteManifests.flatMap((manifest)=>manifest.referenceCssAssets ?? []).map(createAsset)
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'async-entry',
|
|
42
|
+
assets: (routeAssets[`async-${entryName}`]?.referenceCssAssets ?? []).map(createAsset)
|
|
43
|
+
}
|
|
44
|
+
];
|
|
45
|
+
const assets = lifecycle?.transformAssets(groups, {
|
|
46
|
+
kind: 'style',
|
|
47
|
+
source: 'template',
|
|
48
|
+
template,
|
|
49
|
+
createAsset
|
|
50
|
+
}) ?? groups.flatMap((group)=>group.assets);
|
|
51
|
+
const cssChunks = assets.map((asset)=>asset.url).filter((asset)=>asset.endsWith('.css') && !hasStylesheetLink(template, asset));
|
|
45
52
|
const { inlineStyles } = config;
|
|
46
53
|
const styles = cssChunks.map((chunk)=>{
|
|
47
54
|
const link = `<link href="${chunk}" rel="stylesheet" />`;
|