@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.
Files changed (213) hide show
  1. package/dist/cjs/cli/code.js +3 -1
  2. package/dist/cjs/cli/ssr/index.js +2 -74
  3. package/dist/cjs/cli/ssr/loadable-bundler-plugin.js +2 -0
  4. package/dist/cjs/cli/template.server.js +1 -2
  5. package/dist/cjs/core/browser/hydrate.js +9 -10
  6. package/dist/cjs/core/browser/index.js +4 -5
  7. package/dist/cjs/core/context/index.js +12 -45
  8. package/dist/cjs/core/context/public.js +4 -7
  9. package/dist/cjs/core/context/runtime.js +10 -4
  10. package/dist/cjs/core/index.js +3 -3
  11. package/dist/cjs/core/plugin/index.js +2 -2
  12. package/dist/cjs/core/react/index.js +3 -3
  13. package/dist/cjs/core/react/wrapper.js +23 -67
  14. package/dist/cjs/core/server/helmet.js +5 -4
  15. package/dist/cjs/core/server/requestHandler.js +6 -7
  16. package/dist/cjs/core/server/requestResponse.js +4 -4
  17. package/dist/cjs/core/server/routerCleanup.js +2 -2
  18. package/dist/cjs/core/server/shared.js +171 -4
  19. package/dist/cjs/core/server/stream/afterTemplate.js +21 -16
  20. package/dist/cjs/core/server/stream/beforeTemplate.js +37 -28
  21. package/dist/cjs/core/server/stream/beforeTemplate.worker.js +30 -23
  22. package/dist/cjs/core/server/stream/createReadableStream.js +222 -125
  23. package/dist/cjs/core/server/stream/createReadableStream.worker.js +171 -90
  24. package/dist/cjs/core/server/stream/deferredScript.js +3 -3
  25. package/dist/cjs/core/server/stream/shared.js +6 -2
  26. package/dist/cjs/core/server/string/index.js +104 -66
  27. package/dist/cjs/core/server/string/loadable.js +38 -23
  28. package/dist/cjs/core/server/string/ssrData.js +5 -12
  29. package/dist/cjs/core/server/utils.js +1 -2
  30. package/dist/cjs/document/cli/index.js +14 -5
  31. package/dist/cjs/exports/head.js +7 -14
  32. package/dist/cjs/internal.js +2 -2
  33. package/dist/cjs/router/cli/code/nestedRoutes.js +1 -2
  34. package/dist/cjs/router/cli/code/templates.js +1 -1
  35. package/dist/cjs/router/cli/code/utils.js +2 -2
  36. package/dist/cjs/router/runtime/DeferredDataScripts.node.js +10 -9
  37. package/dist/cjs/router/runtime/PrefetchLink.js +69 -125
  38. package/dist/cjs/router/runtime/hooks.js +13 -2
  39. package/dist/cjs/router/runtime/internal.js +7 -45
  40. package/dist/cjs/router/runtime/plugin.js +19 -34
  41. package/dist/cjs/router/runtime/plugin.node.js +9 -37
  42. package/dist/cjs/router/runtime/redirect.js +1 -1
  43. package/dist/esm/cli/code.mjs +3 -1
  44. package/dist/esm/cli/ssr/index.mjs +3 -72
  45. package/dist/esm/cli/ssr/loadable-bundler-plugin.mjs +2 -0
  46. package/dist/esm/cli/template.server.mjs +1 -2
  47. package/dist/esm/core/browser/hydrate.mjs +10 -11
  48. package/dist/esm/core/browser/index.mjs +1 -2
  49. package/dist/esm/core/context/index.mjs +2 -5
  50. package/dist/esm/core/context/public.mjs +1 -5
  51. package/dist/esm/core/context/runtime.mjs +6 -3
  52. package/dist/esm/core/index.mjs +1 -1
  53. package/dist/esm/core/plugin/index.mjs +1 -1
  54. package/dist/esm/core/react/index.mjs +1 -1
  55. package/dist/esm/core/react/wrapper.mjs +20 -67
  56. package/dist/esm/core/server/helmet.mjs +5 -4
  57. package/dist/esm/core/server/requestHandler.mjs +1 -2
  58. package/dist/esm/core/server/requestResponse.mjs +3 -3
  59. package/dist/esm/core/server/routerCleanup.mjs +1 -1
  60. package/dist/esm/core/server/shared.mjs +153 -1
  61. package/dist/esm/core/server/stream/afterTemplate.mjs +23 -18
  62. package/dist/esm/core/server/stream/beforeTemplate.mjs +40 -31
  63. package/dist/esm/core/server/stream/beforeTemplate.worker.mjs +33 -26
  64. package/dist/esm/core/server/stream/createReadableStream.mjs +220 -123
  65. package/dist/esm/core/server/stream/createReadableStream.worker.mjs +161 -90
  66. package/dist/esm/core/server/stream/deferredScript.mjs +3 -3
  67. package/dist/esm/core/server/stream/shared.mjs +4 -3
  68. package/dist/esm/core/server/string/index.mjs +106 -68
  69. package/dist/esm/core/server/string/loadable.mjs +38 -23
  70. package/dist/esm/core/server/string/ssrData.mjs +5 -12
  71. package/dist/esm/core/server/utils.mjs +1 -2
  72. package/dist/esm/document/cli/index.mjs +12 -6
  73. package/dist/esm/exports/head.mjs +7 -14
  74. package/dist/esm/internal.mjs +1 -1
  75. package/dist/esm/router/cli/code/nestedRoutes.mjs +1 -2
  76. package/dist/esm/router/cli/code/templates.mjs +1 -1
  77. package/dist/esm/router/cli/code/utils.mjs +2 -2
  78. package/dist/esm/router/runtime/DeferredDataScripts.node.mjs +10 -9
  79. package/dist/esm/router/runtime/PrefetchLink.mjs +68 -124
  80. package/dist/esm/router/runtime/hooks.mjs +9 -1
  81. package/dist/esm/router/runtime/internal.mjs +2 -33
  82. package/dist/esm/router/runtime/plugin.mjs +10 -25
  83. package/dist/esm/router/runtime/plugin.node.mjs +3 -31
  84. package/dist/esm/router/runtime/redirect.mjs +1 -1
  85. package/dist/esm-node/cli/code.mjs +3 -1
  86. package/dist/esm-node/cli/ssr/index.mjs +3 -72
  87. package/dist/esm-node/cli/ssr/loadable-bundler-plugin.mjs +2 -0
  88. package/dist/esm-node/cli/template.server.mjs +1 -2
  89. package/dist/esm-node/core/browser/hydrate.mjs +10 -11
  90. package/dist/esm-node/core/browser/index.mjs +1 -2
  91. package/dist/esm-node/core/context/index.mjs +2 -5
  92. package/dist/esm-node/core/context/public.mjs +1 -5
  93. package/dist/esm-node/core/context/runtime.mjs +6 -3
  94. package/dist/esm-node/core/index.mjs +1 -1
  95. package/dist/esm-node/core/plugin/index.mjs +1 -1
  96. package/dist/esm-node/core/react/index.mjs +1 -1
  97. package/dist/esm-node/core/react/wrapper.mjs +20 -67
  98. package/dist/esm-node/core/server/helmet.mjs +5 -4
  99. package/dist/esm-node/core/server/requestHandler.mjs +1 -2
  100. package/dist/esm-node/core/server/requestResponse.mjs +3 -3
  101. package/dist/esm-node/core/server/routerCleanup.mjs +1 -1
  102. package/dist/esm-node/core/server/shared.mjs +153 -1
  103. package/dist/esm-node/core/server/stream/afterTemplate.mjs +23 -18
  104. package/dist/esm-node/core/server/stream/beforeTemplate.mjs +40 -31
  105. package/dist/esm-node/core/server/stream/beforeTemplate.worker.mjs +33 -26
  106. package/dist/esm-node/core/server/stream/createReadableStream.mjs +220 -123
  107. package/dist/esm-node/core/server/stream/createReadableStream.worker.mjs +161 -90
  108. package/dist/esm-node/core/server/stream/deferredScript.mjs +3 -3
  109. package/dist/esm-node/core/server/stream/shared.mjs +4 -3
  110. package/dist/esm-node/core/server/string/index.mjs +106 -68
  111. package/dist/esm-node/core/server/string/loadable.mjs +38 -23
  112. package/dist/esm-node/core/server/string/ssrData.mjs +5 -12
  113. package/dist/esm-node/core/server/utils.mjs +1 -2
  114. package/dist/esm-node/document/cli/index.mjs +12 -6
  115. package/dist/esm-node/exports/head.mjs +7 -14
  116. package/dist/esm-node/internal.mjs +1 -1
  117. package/dist/esm-node/router/cli/code/nestedRoutes.mjs +1 -2
  118. package/dist/esm-node/router/cli/code/templates.mjs +1 -1
  119. package/dist/esm-node/router/cli/code/utils.mjs +2 -2
  120. package/dist/esm-node/router/runtime/DeferredDataScripts.node.mjs +10 -9
  121. package/dist/esm-node/router/runtime/PrefetchLink.mjs +68 -124
  122. package/dist/esm-node/router/runtime/hooks.mjs +9 -1
  123. package/dist/esm-node/router/runtime/internal.mjs +2 -33
  124. package/dist/esm-node/router/runtime/plugin.mjs +10 -25
  125. package/dist/esm-node/router/runtime/plugin.node.mjs +3 -31
  126. package/dist/esm-node/router/runtime/redirect.mjs +1 -1
  127. package/dist/types/cli/ssr/index.d.ts +0 -3
  128. package/dist/types/core/context/index.d.ts +4 -6
  129. package/dist/types/core/context/public.d.ts +1 -23
  130. package/dist/types/core/context/runtime.d.ts +26 -2
  131. package/dist/types/core/index.d.ts +1 -1
  132. package/dist/types/core/react/wrapper.d.ts +7 -1
  133. package/dist/types/core/server/helmet.d.ts +4 -5
  134. package/dist/types/core/server/requestHandler.d.ts +3 -3
  135. package/dist/types/core/server/requestResponse.d.ts +1 -1
  136. package/dist/types/core/server/routerCleanup.d.ts +1 -1
  137. package/dist/types/core/server/shared.d.ts +24 -1
  138. package/dist/types/core/server/stream/afterTemplate.d.ts +2 -1
  139. package/dist/types/core/server/stream/beforeTemplate.d.ts +4 -1
  140. package/dist/types/core/server/stream/beforeTemplate.worker.d.ts +4 -1
  141. package/dist/types/core/server/stream/shared.d.ts +16 -2
  142. package/dist/types/core/server/string/loadable.d.ts +6 -3
  143. package/dist/types/core/server/string/ssrData.d.ts +2 -1
  144. package/dist/types/core/server/string/types.d.ts +1 -5
  145. package/dist/types/core/server/tracer.d.ts +1 -1
  146. package/dist/types/core/server/utils.d.ts +1 -1
  147. package/dist/types/core/types.d.ts +1 -2
  148. package/dist/types/document/cli/index.d.ts +1 -0
  149. package/dist/types/exports/head.d.ts +2 -2
  150. package/dist/types/internal.d.ts +1 -1
  151. package/dist/types/router/runtime/PrefetchLink.d.ts +27 -2
  152. package/dist/types/router/runtime/hooks.d.ts +19 -2
  153. package/dist/types/router/runtime/internal.d.ts +4 -21
  154. package/dist/types/router/runtime/types.d.ts +2 -43
  155. package/package.json +18 -46
  156. package/rslib.config.mts +3 -0
  157. package/rstest.config.mts +28 -2
  158. package/dist/cjs/boundary-debugger/index.js +0 -317
  159. package/dist/cjs/core/context/extensions.js +0 -74
  160. package/dist/cjs/core/context/helmetContext.js +0 -54
  161. package/dist/cjs/core/server/federatedCss.js +0 -58
  162. package/dist/cjs/core/server/scriptOrder.js +0 -140
  163. package/dist/cjs/module-federation/consume-surface.js +0 -199
  164. package/dist/cjs/module-federation/distributed-ssr.js +0 -135
  165. package/dist/cjs/module-federation/index.js +0 -316
  166. package/dist/cjs/module-federation/last-known-good.js +0 -157
  167. package/dist/cjs/module-federation/manifest-recovery-runtime-plugin.js +0 -129
  168. package/dist/cjs/module-federation/surface-resolution-types.js +0 -61
  169. package/dist/cjs/router/runtime/lifecycle.js +0 -167
  170. package/dist/cjs/router/runtime/provider.js +0 -153
  171. package/dist/cjs/rsc/server.worker.js +0 -62
  172. package/dist/esm/boundary-debugger/index.mjs +0 -277
  173. package/dist/esm/core/context/extensions.mjs +0 -33
  174. package/dist/esm/core/context/helmetContext.mjs +0 -13
  175. package/dist/esm/core/server/federatedCss.mjs +0 -20
  176. package/dist/esm/core/server/scriptOrder.mjs +0 -90
  177. package/dist/esm/module-federation/consume-surface.mjs +0 -158
  178. package/dist/esm/module-federation/distributed-ssr.mjs +0 -82
  179. package/dist/esm/module-federation/index.mjs +0 -115
  180. package/dist/esm/module-federation/last-known-good.mjs +0 -113
  181. package/dist/esm/module-federation/manifest-recovery-runtime-plugin.mjs +0 -89
  182. package/dist/esm/module-federation/surface-resolution-types.mjs +0 -8
  183. package/dist/esm/router/runtime/lifecycle.mjs +0 -105
  184. package/dist/esm/router/runtime/provider.mjs +0 -100
  185. package/dist/esm/rsc/server.worker.mjs +0 -1
  186. package/dist/esm-node/boundary-debugger/index.mjs +0 -278
  187. package/dist/esm-node/core/context/extensions.mjs +0 -34
  188. package/dist/esm-node/core/context/helmetContext.mjs +0 -14
  189. package/dist/esm-node/core/server/federatedCss.mjs +0 -21
  190. package/dist/esm-node/core/server/scriptOrder.mjs +0 -91
  191. package/dist/esm-node/module-federation/consume-surface.mjs +0 -159
  192. package/dist/esm-node/module-federation/distributed-ssr.mjs +0 -83
  193. package/dist/esm-node/module-federation/index.mjs +0 -116
  194. package/dist/esm-node/module-federation/last-known-good.mjs +0 -114
  195. package/dist/esm-node/module-federation/manifest-recovery-runtime-plugin.mjs +0 -90
  196. package/dist/esm-node/module-federation/surface-resolution-types.mjs +0 -9
  197. package/dist/esm-node/router/runtime/lifecycle.mjs +0 -106
  198. package/dist/esm-node/router/runtime/provider.mjs +0 -101
  199. package/dist/esm-node/rsc/server.worker.mjs +0 -2
  200. package/dist/types/boundary-debugger/index.d.ts +0 -28
  201. package/dist/types/core/context/extensions.d.ts +0 -35
  202. package/dist/types/core/context/helmetContext.d.ts +0 -10
  203. package/dist/types/core/server/federatedCss.d.ts +0 -5
  204. package/dist/types/core/server/scriptOrder.d.ts +0 -25
  205. package/dist/types/module-federation/consume-surface.d.ts +0 -104
  206. package/dist/types/module-federation/distributed-ssr.d.ts +0 -61
  207. package/dist/types/module-federation/index.d.ts +0 -71
  208. package/dist/types/module-federation/last-known-good.d.ts +0 -52
  209. package/dist/types/module-federation/manifest-recovery-runtime-plugin.d.ts +0 -25
  210. package/dist/types/module-federation/surface-resolution-types.d.ts +0 -23
  211. package/dist/types/router/runtime/lifecycle.d.ts +0 -27
  212. package/dist/types/router/runtime/provider.d.ts +0 -78
  213. 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 { HelmetProvider } from "react-helmet-async";
3
- import { InternalRuntimeContext, RuntimeContext, getGlobalEnableRsc, getInitialContext } from "../context/index.mjs";
4
- import { stripRuntimeContextExtensions } from "../context/extensions.mjs";
5
- import { ensureHelmetContext } from "../context/helmetContext.mjs";
6
- function createRscSafeRequestContext(ssrContext) {
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
- stripRuntimeContextExtensions(runtimeContextValue);
51
- if (true === getGlobalEnableRsc() && false === isBrowser) {
52
- const rscSafeRequestContext = createRscSafeRequestContext(ssrContext);
53
- const rscInternalContextValue = {
54
- ...internalContextValue,
55
- context: rscSafeRequestContext,
56
- requestContext: rscSafeRequestContext
57
- };
58
- delete rscInternalContextValue.ssrContext;
59
- const rscRuntimeContextValue = {
60
- ...runtimeContextValue,
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: runtimeContextValue,
76
- children: /*#__PURE__*/ jsx(HelmetProvider, {
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(runtimeContext) {
10
- return getHelmetContext(runtimeContext)?.helmet ?? void 0;
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.toString();
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 "../../router/runtime/lifecycle.mjs";
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 (!redirectUrl) return;
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 "../../router/runtime/lifecycle.mjs";
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
- export { buildHtml };
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 { createRouteHydrationScriptTags, replaceChunkJsPlaceholder } from "../scriptOrder.mjs";
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
- entryName
17
+ lifecycle
20
18
  })
21
19
  ];
22
20
  async function injectJs(template, entryName, nonce) {
23
- const jsChunkStr = createRouteHydrationScriptTags(runtimeContext, entryName, {
24
- nonce,
25
- template
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, entryName } = options;
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
- const hydrationScripts = getRouterHydrationScripts(runtimeContext);
63
- const ssrScripts = hydrationScripts.length ? `${ssrDataScript}\n${hydrationScripts.join('\n')}` : ssrDataScript;
64
- return (template)=>{
65
- if (!template.includes(SSR_DATA_PLACEHOLDER)) return template;
66
- return replaceChunkJsPlaceholder(template, ssrScripts, entryName, SSR_DATA_PLACEHOLDER);
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 { createFederatedCssLinks } from "../federatedCss.mjs";
5
- import { createReplaceHelemt, getHelmetData } from "../helmet.mjs";
6
- import { buildHtml } from "../shared.mjs";
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, moduleFederationCssAssets } = options;
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
- css += createFederatedCssLinks(moduleFederationCssAssets, {
27
+ return replaceSSRTemplateChunk({
28
+ name: 'styles',
31
29
  template,
32
- existingAssets: css.match(/href="([^"]+)"/g)?.map((item)=>item.replace(/^href="/, '').replace(/"$/, ''))
33
- });
34
- return safeReplace(template, CHUNK_CSS_PLACEHOLDER, css);
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
- const matchedRouteIds = getRouterMatchedRouteIds(runtimeContext);
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?.map((match, index)=>{
45
- if (!index) return;
41
+ matchedRouteManifests = matches?.flatMap((match, index)=>{
46
42
  const routeId = match.route.id;
47
- if (routeId) return routeAssets[routeId];
48
- }).filter((routeManifest)=>void 0 !== routeManifest) ?? [];
43
+ const manifest = 0 !== index && routeId ? routeAssets[routeId] : void 0;
44
+ return void 0 === manifest ? [] : [
45
+ manifest
46
+ ];
47
+ }) ?? [];
49
48
  }
50
- const asyncEntry = routeAssets[`async-${entryName}`];
51
- if (asyncEntry) matchedRouteManifests.push(asyncEntry);
52
- const cssChunks = matchedRouteManifests.reduce((chunks, routeManifest)=>{
53
- const { referenceCssAssets = [] } = routeManifest;
54
- const _cssChunks = referenceCssAssets.filter((asset)=>asset?.endsWith('.css') && !hasStylesheetLink(template, asset));
55
- return [
56
- ...chunks,
57
- ..._cssChunks
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 { createFederatedCssLinks } from "../federatedCss.mjs";
4
- import { createReplaceHelemt, getHelmetData } from "../helmet.mjs";
5
- import { buildHtml } from "../shared.mjs";
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, moduleFederationCssAssets } = options;
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
- css += createFederatedCssLinks(moduleFederationCssAssets, {
20
+ return replaceSSRTemplateChunk({
21
+ name: 'styles',
24
22
  template,
25
- existingAssets: css.match(/href="([^"]+)"/g)?.map((item)=>item.replace(/^href="/, '').replace(/"$/, ''))
26
- });
27
- return safeReplace(template, CHUNK_CSS_PLACEHOLDER, css);
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
- let matchedRouteManifests = [];
33
- const matchedRouteIds = getRouterMatchedRouteIds(runtimeContext);
34
- if (matchedRouteIds?.length) matchedRouteManifests = matchedRouteIds.map((routeId)=>routeAssets[routeId]).filter(Boolean);
35
- const asyncEntry = routeAssets[`async-${entryName}`];
36
- if (asyncEntry) matchedRouteManifests.push(asyncEntry);
37
- const cssChunks = matchedRouteManifests.reduce((chunks, routeManifest)=>{
38
- const { referenceCssAssets = [] } = routeManifest;
39
- const _cssChunks = referenceCssAssets.filter((asset)=>asset?.endsWith('.css') && !hasStylesheetLink(template, asset));
40
- return [
41
- ...chunks,
42
- ..._cssChunks
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" />`;