@bleedingdev/modern-js-runtime 3.9.0-ultramodern.2 → 3.9.0-ultramodern.20

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 (209) 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/exports/head.js +7 -14
  31. package/dist/cjs/internal.js +2 -2
  32. package/dist/cjs/router/cli/code/nestedRoutes.js +1 -2
  33. package/dist/cjs/router/cli/code/templates.js +1 -1
  34. package/dist/cjs/router/cli/code/utils.js +2 -2
  35. package/dist/cjs/router/runtime/DeferredDataScripts.node.js +10 -9
  36. package/dist/cjs/router/runtime/PrefetchLink.js +69 -125
  37. package/dist/cjs/router/runtime/hooks.js +13 -2
  38. package/dist/cjs/router/runtime/internal.js +7 -45
  39. package/dist/cjs/router/runtime/plugin.js +19 -34
  40. package/dist/cjs/router/runtime/plugin.node.js +9 -37
  41. package/dist/cjs/router/runtime/redirect.js +1 -1
  42. package/dist/esm/cli/code.mjs +3 -1
  43. package/dist/esm/cli/ssr/index.mjs +3 -72
  44. package/dist/esm/cli/ssr/loadable-bundler-plugin.mjs +2 -0
  45. package/dist/esm/cli/template.server.mjs +1 -2
  46. package/dist/esm/core/browser/hydrate.mjs +10 -11
  47. package/dist/esm/core/browser/index.mjs +1 -2
  48. package/dist/esm/core/context/index.mjs +2 -5
  49. package/dist/esm/core/context/public.mjs +1 -5
  50. package/dist/esm/core/context/runtime.mjs +6 -3
  51. package/dist/esm/core/index.mjs +1 -1
  52. package/dist/esm/core/plugin/index.mjs +1 -1
  53. package/dist/esm/core/react/index.mjs +1 -1
  54. package/dist/esm/core/react/wrapper.mjs +20 -67
  55. package/dist/esm/core/server/helmet.mjs +5 -4
  56. package/dist/esm/core/server/requestHandler.mjs +1 -2
  57. package/dist/esm/core/server/requestResponse.mjs +3 -3
  58. package/dist/esm/core/server/routerCleanup.mjs +1 -1
  59. package/dist/esm/core/server/shared.mjs +153 -1
  60. package/dist/esm/core/server/stream/afterTemplate.mjs +23 -18
  61. package/dist/esm/core/server/stream/beforeTemplate.mjs +40 -31
  62. package/dist/esm/core/server/stream/beforeTemplate.worker.mjs +33 -26
  63. package/dist/esm/core/server/stream/createReadableStream.mjs +220 -123
  64. package/dist/esm/core/server/stream/createReadableStream.worker.mjs +161 -90
  65. package/dist/esm/core/server/stream/deferredScript.mjs +3 -3
  66. package/dist/esm/core/server/stream/shared.mjs +4 -3
  67. package/dist/esm/core/server/string/index.mjs +106 -68
  68. package/dist/esm/core/server/string/loadable.mjs +38 -23
  69. package/dist/esm/core/server/string/ssrData.mjs +5 -12
  70. package/dist/esm/core/server/utils.mjs +1 -2
  71. package/dist/esm/exports/head.mjs +7 -14
  72. package/dist/esm/internal.mjs +1 -1
  73. package/dist/esm/router/cli/code/nestedRoutes.mjs +1 -2
  74. package/dist/esm/router/cli/code/templates.mjs +1 -1
  75. package/dist/esm/router/cli/code/utils.mjs +2 -2
  76. package/dist/esm/router/runtime/DeferredDataScripts.node.mjs +10 -9
  77. package/dist/esm/router/runtime/PrefetchLink.mjs +68 -124
  78. package/dist/esm/router/runtime/hooks.mjs +9 -1
  79. package/dist/esm/router/runtime/internal.mjs +2 -33
  80. package/dist/esm/router/runtime/plugin.mjs +10 -25
  81. package/dist/esm/router/runtime/plugin.node.mjs +3 -31
  82. package/dist/esm/router/runtime/redirect.mjs +1 -1
  83. package/dist/esm-node/cli/code.mjs +3 -1
  84. package/dist/esm-node/cli/ssr/index.mjs +3 -72
  85. package/dist/esm-node/cli/ssr/loadable-bundler-plugin.mjs +2 -0
  86. package/dist/esm-node/cli/template.server.mjs +1 -2
  87. package/dist/esm-node/core/browser/hydrate.mjs +10 -11
  88. package/dist/esm-node/core/browser/index.mjs +1 -2
  89. package/dist/esm-node/core/context/index.mjs +2 -5
  90. package/dist/esm-node/core/context/public.mjs +1 -5
  91. package/dist/esm-node/core/context/runtime.mjs +6 -3
  92. package/dist/esm-node/core/index.mjs +1 -1
  93. package/dist/esm-node/core/plugin/index.mjs +1 -1
  94. package/dist/esm-node/core/react/index.mjs +1 -1
  95. package/dist/esm-node/core/react/wrapper.mjs +20 -67
  96. package/dist/esm-node/core/server/helmet.mjs +5 -4
  97. package/dist/esm-node/core/server/requestHandler.mjs +1 -2
  98. package/dist/esm-node/core/server/requestResponse.mjs +3 -3
  99. package/dist/esm-node/core/server/routerCleanup.mjs +1 -1
  100. package/dist/esm-node/core/server/shared.mjs +153 -1
  101. package/dist/esm-node/core/server/stream/afterTemplate.mjs +23 -18
  102. package/dist/esm-node/core/server/stream/beforeTemplate.mjs +40 -31
  103. package/dist/esm-node/core/server/stream/beforeTemplate.worker.mjs +33 -26
  104. package/dist/esm-node/core/server/stream/createReadableStream.mjs +220 -123
  105. package/dist/esm-node/core/server/stream/createReadableStream.worker.mjs +161 -90
  106. package/dist/esm-node/core/server/stream/deferredScript.mjs +3 -3
  107. package/dist/esm-node/core/server/stream/shared.mjs +4 -3
  108. package/dist/esm-node/core/server/string/index.mjs +106 -68
  109. package/dist/esm-node/core/server/string/loadable.mjs +38 -23
  110. package/dist/esm-node/core/server/string/ssrData.mjs +5 -12
  111. package/dist/esm-node/core/server/utils.mjs +1 -2
  112. package/dist/esm-node/exports/head.mjs +7 -14
  113. package/dist/esm-node/internal.mjs +1 -1
  114. package/dist/esm-node/router/cli/code/nestedRoutes.mjs +1 -2
  115. package/dist/esm-node/router/cli/code/templates.mjs +1 -1
  116. package/dist/esm-node/router/cli/code/utils.mjs +2 -2
  117. package/dist/esm-node/router/runtime/DeferredDataScripts.node.mjs +10 -9
  118. package/dist/esm-node/router/runtime/PrefetchLink.mjs +68 -124
  119. package/dist/esm-node/router/runtime/hooks.mjs +9 -1
  120. package/dist/esm-node/router/runtime/internal.mjs +2 -33
  121. package/dist/esm-node/router/runtime/plugin.mjs +10 -25
  122. package/dist/esm-node/router/runtime/plugin.node.mjs +3 -31
  123. package/dist/esm-node/router/runtime/redirect.mjs +1 -1
  124. package/dist/types/cli/ssr/index.d.ts +0 -3
  125. package/dist/types/core/context/index.d.ts +4 -6
  126. package/dist/types/core/context/public.d.ts +1 -23
  127. package/dist/types/core/context/runtime.d.ts +26 -2
  128. package/dist/types/core/index.d.ts +1 -1
  129. package/dist/types/core/react/wrapper.d.ts +7 -1
  130. package/dist/types/core/server/helmet.d.ts +4 -5
  131. package/dist/types/core/server/requestHandler.d.ts +3 -3
  132. package/dist/types/core/server/requestResponse.d.ts +1 -1
  133. package/dist/types/core/server/routerCleanup.d.ts +1 -1
  134. package/dist/types/core/server/shared.d.ts +24 -1
  135. package/dist/types/core/server/stream/afterTemplate.d.ts +2 -1
  136. package/dist/types/core/server/stream/beforeTemplate.d.ts +4 -1
  137. package/dist/types/core/server/stream/beforeTemplate.worker.d.ts +4 -1
  138. package/dist/types/core/server/stream/shared.d.ts +16 -2
  139. package/dist/types/core/server/string/loadable.d.ts +6 -3
  140. package/dist/types/core/server/string/ssrData.d.ts +2 -1
  141. package/dist/types/core/server/string/types.d.ts +1 -5
  142. package/dist/types/core/server/tracer.d.ts +1 -1
  143. package/dist/types/core/server/utils.d.ts +1 -1
  144. package/dist/types/core/types.d.ts +1 -2
  145. package/dist/types/exports/head.d.ts +2 -2
  146. package/dist/types/internal.d.ts +1 -1
  147. package/dist/types/router/runtime/PrefetchLink.d.ts +27 -2
  148. package/dist/types/router/runtime/hooks.d.ts +19 -2
  149. package/dist/types/router/runtime/internal.d.ts +4 -21
  150. package/dist/types/router/runtime/types.d.ts +2 -43
  151. package/package.json +18 -46
  152. package/rslib.config.mts +3 -0
  153. package/rstest.config.mts +28 -2
  154. package/dist/cjs/boundary-debugger/index.js +0 -317
  155. package/dist/cjs/core/context/extensions.js +0 -74
  156. package/dist/cjs/core/context/helmetContext.js +0 -54
  157. package/dist/cjs/core/server/federatedCss.js +0 -58
  158. package/dist/cjs/core/server/scriptOrder.js +0 -140
  159. package/dist/cjs/module-federation/consume-surface.js +0 -199
  160. package/dist/cjs/module-federation/distributed-ssr.js +0 -135
  161. package/dist/cjs/module-federation/index.js +0 -316
  162. package/dist/cjs/module-federation/last-known-good.js +0 -157
  163. package/dist/cjs/module-federation/manifest-recovery-runtime-plugin.js +0 -129
  164. package/dist/cjs/module-federation/surface-resolution-types.js +0 -61
  165. package/dist/cjs/router/runtime/lifecycle.js +0 -167
  166. package/dist/cjs/router/runtime/provider.js +0 -153
  167. package/dist/cjs/rsc/server.worker.js +0 -62
  168. package/dist/esm/boundary-debugger/index.mjs +0 -277
  169. package/dist/esm/core/context/extensions.mjs +0 -33
  170. package/dist/esm/core/context/helmetContext.mjs +0 -13
  171. package/dist/esm/core/server/federatedCss.mjs +0 -20
  172. package/dist/esm/core/server/scriptOrder.mjs +0 -90
  173. package/dist/esm/module-federation/consume-surface.mjs +0 -158
  174. package/dist/esm/module-federation/distributed-ssr.mjs +0 -82
  175. package/dist/esm/module-federation/index.mjs +0 -115
  176. package/dist/esm/module-federation/last-known-good.mjs +0 -113
  177. package/dist/esm/module-federation/manifest-recovery-runtime-plugin.mjs +0 -89
  178. package/dist/esm/module-federation/surface-resolution-types.mjs +0 -8
  179. package/dist/esm/router/runtime/lifecycle.mjs +0 -105
  180. package/dist/esm/router/runtime/provider.mjs +0 -100
  181. package/dist/esm/rsc/server.worker.mjs +0 -1
  182. package/dist/esm-node/boundary-debugger/index.mjs +0 -278
  183. package/dist/esm-node/core/context/extensions.mjs +0 -34
  184. package/dist/esm-node/core/context/helmetContext.mjs +0 -14
  185. package/dist/esm-node/core/server/federatedCss.mjs +0 -21
  186. package/dist/esm-node/core/server/scriptOrder.mjs +0 -91
  187. package/dist/esm-node/module-federation/consume-surface.mjs +0 -159
  188. package/dist/esm-node/module-federation/distributed-ssr.mjs +0 -83
  189. package/dist/esm-node/module-federation/index.mjs +0 -116
  190. package/dist/esm-node/module-federation/last-known-good.mjs +0 -114
  191. package/dist/esm-node/module-federation/manifest-recovery-runtime-plugin.mjs +0 -90
  192. package/dist/esm-node/module-federation/surface-resolution-types.mjs +0 -9
  193. package/dist/esm-node/router/runtime/lifecycle.mjs +0 -106
  194. package/dist/esm-node/router/runtime/provider.mjs +0 -101
  195. package/dist/esm-node/rsc/server.worker.mjs +0 -2
  196. package/dist/types/boundary-debugger/index.d.ts +0 -28
  197. package/dist/types/core/context/extensions.d.ts +0 -35
  198. package/dist/types/core/context/helmetContext.d.ts +0 -10
  199. package/dist/types/core/server/federatedCss.d.ts +0 -5
  200. package/dist/types/core/server/scriptOrder.d.ts +0 -25
  201. package/dist/types/module-federation/consume-surface.d.ts +0 -104
  202. package/dist/types/module-federation/distributed-ssr.d.ts +0 -61
  203. package/dist/types/module-federation/index.d.ts +0 -71
  204. package/dist/types/module-federation/last-known-good.d.ts +0 -52
  205. package/dist/types/module-federation/manifest-recovery-runtime-plugin.d.ts +0 -25
  206. package/dist/types/module-federation/surface-resolution-types.d.ts +0 -23
  207. package/dist/types/router/runtime/lifecycle.d.ts +0 -27
  208. package/dist/types/router/runtime/provider.d.ts +0 -78
  209. package/dist/types/rsc/server.worker.d.ts +0 -1
@@ -1,7 +1,5 @@
1
1
  import "node:module";
2
2
  import { ChunkExtractor } from "@loadable/server";
3
- import { createFederatedCssLinks } from "../federatedCss.mjs";
4
- import { getMatchedRouteChunks, orderHydrationScriptChunks } from "../scriptOrder.mjs";
5
3
  import { attributesToString, checkIsNode, hasStylesheetLink } from "../utils.mjs";
6
4
  import { fileURLToPath as __rspack_fileURLToPath } from "node:url";
7
5
  import { dirname as __rspack_dirname } from "node:path";
@@ -11,7 +9,7 @@ const extname = (uri)=>{
11
9
  return `.${uri?.split('.').pop()}` || '';
12
10
  };
13
11
  const generateChunks = (chunks, ext)=>chunks.filter((chunk)=>Boolean(chunk.url)).filter((chunk)=>extname(chunk.url).slice(1) === ext);
14
- const routeAssetToChunk = (asset)=>({
12
+ const assetToChunk = (asset)=>({
15
13
  chunk: asset,
16
14
  filename: asset.replace(/^\//, ''),
17
15
  linkType: 'preload',
@@ -22,8 +20,8 @@ const routeAssetToChunk = (asset)=>({
22
20
  });
23
21
  const checkIsInline = (chunk, enableInline)=>{
24
22
  if ('production' !== process.env.NODE_ENV) return false;
25
- if (enableInline instanceof RegExp) return enableInline.test(chunk.url);
26
- return Boolean(enableInline);
23
+ else if (enableInline instanceof RegExp) return enableInline.test(chunk.url);
24
+ else return Boolean(enableInline);
27
25
  };
28
26
  const readAsset = async (chunk)=>{
29
27
  const fs = await import("fs/promises");
@@ -57,16 +55,32 @@ class LoadableCollector {
57
55
  ]));
58
56
  } catch (e) {}
59
57
  const collectedChunks = extractor ? extractor.getChunkAssets(extractor.chunks) : [];
60
- const matchedRouteChunks = getMatchedRouteChunks(options.runtimeContext, options.routeManifest, routeAssetToChunk);
61
- const orderedScriptChunks = orderHydrationScriptChunks({
62
- asyncEntryChunks: asyncChunks,
63
- collectedChunks,
64
- matchedRouteChunks,
65
- entryName
66
- });
67
- const chunks = [].concat(asyncChunks).concat(collectedChunks).concat(matchedRouteChunks);
68
- const scriptChunks = generateChunks(orderedScriptChunks, 'js');
69
- const styleChunks = generateChunks(chunks, 'css');
58
+ const groups = [
59
+ {
60
+ name: 'async-entry',
61
+ assets: asyncChunks
62
+ },
63
+ {
64
+ name: 'loadable',
65
+ assets: collectedChunks
66
+ }
67
+ ];
68
+ const nativeChunks = [
69
+ ...asyncChunks,
70
+ ...collectedChunks
71
+ ];
72
+ const prepare = (kind)=>options.lifecycle?.transformAssets(groups, {
73
+ kind,
74
+ source: 'loadable',
75
+ template: options.template,
76
+ createAsset: assetToChunk
77
+ }) ?? nativeChunks;
78
+ const scriptChunks = generateChunks([
79
+ ...prepare("script")
80
+ ], 'js');
81
+ const styleChunks = generateChunks([
82
+ ...prepare('style')
83
+ ], 'css');
70
84
  if (extractor) {
71
85
  this.emitLoadableScripts(extractor);
72
86
  await this.emitScriptAssets(scriptChunks);
@@ -100,12 +114,12 @@ class LoadableCollector {
100
114
  const scripts = await Promise.all(chunks.filter((chunk)=>!existedScript.includes(chunk.url) && !this.existsAssets?.includes(chunk.path)).map(async (chunk)=>{
101
115
  const script = `<script${attributes} src="${chunk.url}"></script>`;
102
116
  if (checkIsNode() && checkIsInline(chunk, inlineStyles)) return readAsset(chunk).then((content)=>`<script>${content}</script>`).catch((_)=>script);
103
- return script;
117
+ else return script;
104
118
  }));
105
119
  chunkSet.jsChunk += scripts.filter((script)=>Boolean(script)).join('');
106
120
  }
107
121
  async emitStyleAssets(chunks) {
108
- const { template, chunkSet, config, moduleFederationCssAssets } = this.options;
122
+ const { template, chunkSet, config } = this.options;
109
123
  const { inlineStyles } = config;
110
124
  const atrributes = attributesToString(this.generateAttributes());
111
125
  const emittedAssetUrls = new Set();
@@ -117,14 +131,11 @@ class LoadableCollector {
117
131
  const css = await Promise.all(emittedChunks.map(async (chunk)=>{
118
132
  const link = `<link${atrributes} href="${chunk.url}" rel="stylesheet" />`;
119
133
  if (checkIsNode() && checkIsInline(chunk, inlineStyles)) return readAsset(chunk).then((content)=>`<style>${content}</style>`).catch((_)=>link);
120
- return link;
134
+ else return link;
121
135
  }));
122
136
  chunkSet.cssChunk += css.filter((css)=>Boolean(css)).join('');
123
- chunkSet.cssChunk += createFederatedCssLinks(moduleFederationCssAssets, {
124
- template,
125
- attributes: this.generateAttributes(),
126
- existingAssets: emittedChunks.map((chunk)=>chunk.url)
127
- });
137
+ this.stylesheetInfo.emittedAssets = emittedChunks.map((chunk)=>chunk.url);
138
+ this.stylesheetInfo.attributes = this.generateAttributes();
128
139
  }
129
140
  generateAttributes(extraAtr = {}) {
130
141
  const { config } = this.options;
@@ -137,6 +148,10 @@ class LoadableCollector {
137
148
  };
138
149
  }
139
150
  constructor(options){
151
+ this.stylesheetInfo = {
152
+ emittedAssets: [],
153
+ attributes: {}
154
+ };
140
155
  this.options = options;
141
156
  }
142
157
  }
@@ -1,6 +1,5 @@
1
1
  import "node:module";
2
2
  import { serializeJson } from "@modern-js/runtime-utils/node";
3
- import { getRouterHydrationScripts, getRouterServerSnapshot } from "../../../router/runtime/lifecycle.mjs";
4
3
  import { ROUTER_DATA_JSON_ID, SSR_DATA_JSON_ID } from "../../constants.mjs";
5
4
  import { attributesToString, serializeErrors } from "../utils.mjs";
6
5
  function _check_private_redeclaration(obj, privateCollection) {
@@ -89,20 +88,15 @@ function getSSRData() {
89
88
  };
90
89
  }
91
90
  function getRouterData() {
92
- const { routerContext, runtimeContext } = _class_private_field_get(this, _options);
93
- const snapshotRouterData = getRouterServerSnapshot(runtimeContext)?.routerData;
94
- if (snapshotRouterData) return {
95
- loaderData: snapshotRouterData.loaderData,
96
- errors: serializeErrors(snapshotRouterData.errors || null)
97
- };
98
- return routerContext ? {
99
- loaderData: routerContext.loaderData,
100
- errors: serializeErrors(routerContext.errors)
91
+ const { routerContext, lifecycle } = _class_private_field_get(this, _options);
92
+ const data = lifecycle?.getRouterData() ?? routerContext;
93
+ return data ? {
94
+ loaderData: data.loaderData,
95
+ errors: serializeErrors(data.errors || null)
101
96
  } : void 0;
102
97
  }
103
98
  function getSSRDataScripts(ssrData, routerData) {
104
99
  const { nonce, useJsonScript = false } = _class_private_field_get(this, _options);
105
- const hydrationScripts = getRouterHydrationScripts(_class_private_field_get(this, _options).runtimeContext);
106
100
  const serializeSSRData = serializeJson(ssrData);
107
101
  const attrsStr = attributesToString({
108
102
  nonce
@@ -112,7 +106,6 @@ function getSSRDataScripts(ssrData, routerData) {
112
106
  const serializedRouterData = serializeJson(routerData);
113
107
  ssrDataScripts += useJsonScript ? `\n<script type="application/json" id="${ROUTER_DATA_JSON_ID}">${serializedRouterData}</script>` : `\n<script${attrsStr}>window._ROUTER_DATA = ${serializedRouterData}</script>`;
114
108
  }
115
- if (hydrationScripts.length) ssrDataScripts += `\n${hydrationScripts.join('\n')}`;
116
109
  return ssrDataScripts;
117
110
  }
118
111
  export { SSRDataCollector };
@@ -1,8 +1,7 @@
1
1
  import "node:module";
2
- import { escapeHtmlAttribute, isSafeHtmlAttributeName } from "@modern-js/runtime-extensions";
3
2
  import { isRouteErrorResponse } from "../../router/runtime/routerHelper.mjs";
4
3
  function attributesToString(attributes) {
5
- return Object.entries(attributes).reduce((str, [key, value])=>void 0 !== value && isSafeHtmlAttributeName(key) ? `${str} ${key}="${escapeHtmlAttribute(value)}"` : str, '');
4
+ return Object.entries(attributes).reduce((str, [key, value])=>void 0 !== value && /^[^\u0000-\u0020"'<>/=]+$/u.test(key) ? `${str} ${key}="${String(value).replaceAll('&', '&amp;').replaceAll('"', '&quot;').replaceAll('<', '&lt;').replaceAll('>', '&gt;')}"` : str, '');
6
5
  }
7
6
  function safeReplace(source, searchValue, replaceValue) {
8
7
  return source.replace(searchValue, ()=>replaceValue);
@@ -1,22 +1,15 @@
1
1
  import "node:module";
2
2
  "use client";
3
+ import { RuntimeComponentResolverContext } from "@modern-js/runtime/context";
3
4
  import react from "react";
4
5
  import { Helmet, HelmetData, HelmetProvider } from "react-helmet-async";
5
- import { InternalRuntimeContext } from "../core/context/index.mjs";
6
- import { ensureHelmetContext } from "../core/context/helmetContext.mjs";
7
- import * as __rspack_external__modern_js_runtime_extensions_ce611631 from "@modern-js/runtime-extensions";
8
- const collectServerHelmet = (runtimeContext, props)=>{
9
- const helmetContext = ensureHelmetContext(runtimeContext);
10
- const createRecord = ()=>__rspack_external__modern_js_runtime_extensions_ce611631.createHelmetRecord(react, props);
11
- const deriveState = (records)=>__rspack_external__modern_js_runtime_extensions_ce611631.deriveHelmetServerState(react, records);
12
- const marker = __rspack_external__modern_js_runtime_extensions_ce611631.collectHeadState(runtimeContext, createRecord, deriveState, helmetContext);
13
- if (void 0 !== marker) return marker;
14
- helmetContext.helmet = __rspack_external__modern_js_runtime_extensions_ce611631.collectImmediateHelmetState(react, helmetContext, createRecord());
15
- };
16
6
  const head_Helmet = (props)=>{
17
- const runtimeContext = react.useContext(InternalRuntimeContext);
18
- if (null !== runtimeContext && false === runtimeContext.isBrowser) return __rspack_external__modern_js_runtime_extensions_ce611631.renderHeadMarker(react, collectServerHelmet(runtimeContext, props));
19
- return react.createElement(Helmet, props);
7
+ const resolveComponent = react.useContext(RuntimeComponentResolverContext);
8
+ const Component = resolveComponent?.(Helmet, {
9
+ name: 'head.Helmet'
10
+ }) ?? Helmet;
11
+ if (Component === head_Helmet) throw new Error('A component resolver cannot resolve head.Helmet to itself.');
12
+ return react.createElement(Component, props);
20
13
  };
21
14
  const head = {
22
15
  Helmet: head_Helmet,
@@ -1,2 +1,2 @@
1
1
  import "node:module";
2
- export { InternalRuntimeContext } from "./core/context/runtime.mjs";
2
+ export { InternalRuntimeContext } from "@modern-js/runtime/context";
@@ -43,8 +43,7 @@ const optimizeRoute = (routeTree)=>{
43
43
  children: optimizedChildren
44
44
  }
45
45
  ];
46
- }
47
- {
46
+ } else {
48
47
  const newRoutes = children.map((child)=>{
49
48
  const routePath = routeTree.path ? `${routeTree.path}${child.path ? `/${child.path}` : ''}` : child.path || '';
50
49
  const newRoute = {
@@ -379,7 +379,7 @@ const runtimeGlobalContext = async ({ entryName, metaName, srcDirectory, nestedR
379
379
  enableRsc: true,
380
380
  });
381
381
  `;
382
- return `${imports.join('\n')}
382
+ else return `${imports.join('\n')}
383
383
 
384
384
  import { routes } from '${routesImportPath}';
385
385
 
@@ -11,7 +11,7 @@ const walkDirectory = (dir)=>fs_0.readdirSync(dir).reduce((previous, filename)=>
11
11
  ...previous,
12
12
  ...walkDirectory(filePath)
13
13
  ];
14
- return [
14
+ else return [
15
15
  ...previous,
16
16
  filePath
17
17
  ];
@@ -28,7 +28,7 @@ const isPageComponentFile = (filePath)=>{
28
28
  };
29
29
  const replaceWithAlias = (base, filePath, alias)=>{
30
30
  if (filePath.includes(base)) return normalizeToPosixPath(path.join(alias, path.relative(base, filePath)));
31
- return filePath;
31
+ else return filePath;
32
32
  };
33
33
  const parseModule = async ({ source, filename })=>{
34
34
  let content = source;
@@ -52,7 +52,7 @@ const DeferredDataScripts = (props)=>{
52
52
  serializeJson(key)
53
53
  ]
54
54
  };
55
- {
55
+ else {
56
56
  const trackedPromise = deferredData.data[key];
57
57
  if (void 0 !== trackedPromise._error) {
58
58
  const error = toDeferredErrorInfo(trackedPromise._error);
@@ -64,15 +64,16 @@ const DeferredDataScripts = (props)=>{
64
64
  serializeJson(error)
65
65
  ]
66
66
  };
67
+ } else {
68
+ if (void 0 === trackedPromise._data) throw new Error(`The deferred data for ${key} was not resolved, did you forget to return data from a deferred promise`);
69
+ return {
70
+ key,
71
+ routerDataFnName: 'p',
72
+ routerDataFnArgs: [
73
+ serializeJson(trackedPromise._data)
74
+ ]
75
+ };
67
76
  }
68
- if (void 0 === trackedPromise._data) throw new Error(`The deferred data for ${key} was not resolved, did you forget to return data from a deferred promise`);
69
- return {
70
- key,
71
- routerDataFnName: 'p',
72
- routerDataFnArgs: [
73
- serializeJson(trackedPromise._data)
74
- ]
75
- };
76
77
  }
77
78
  });
78
79
  return {
@@ -1,10 +1,9 @@
1
1
  import "node:module";
2
2
  "use client";
3
3
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
- import { getNavigationWarmupCacheKey } from "@modern-js/runtime-extensions";
4
+ import { InternalRuntimeContext } from "@modern-js/runtime/context";
5
5
  import { Link as router_Link, NavLink, matchRoutes, useHref, useMatches, useResolvedPath } from "@modern-js/runtime-utils/router";
6
6
  import react, { useContext, useMemo } from "react";
7
- import { InternalRuntimeContext } from "../../core/context/index.mjs";
8
7
  import { __webpack_require__ } from "../../rslib-runtime~0.mjs";
9
8
  const getWebpackChunkLoader = ()=>__webpack_chunk_load__;
10
9
  const getWebpackPublicPath = ()=>{
@@ -21,62 +20,6 @@ function composeEventHandlers(theirHandler, ourHandler) {
21
20
  };
22
21
  }
23
22
  const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
24
- const DEFAULT_PREFETCH_BEHAVIOR = 'render';
25
- const INTENT_DELAY = 100;
26
- const VIEWPORT_ROOT_MARGIN = '200px';
27
- const MAX_CONCURRENT_WARMUPS = 4;
28
- const WARMUP_TTL = 30000;
29
- const SLOW_EFFECTIVE_TYPES = new Set([
30
- 'slow-2g',
31
- '2g'
32
- ]);
33
- const warmupCache = new Map();
34
- const warmupQueue = [];
35
- let activeWarmups = 0;
36
- const getWarmupTimestamp = ()=>performance.now();
37
- const getConnection = ()=>{
38
- const nav = globalThis.navigator;
39
- return nav?.connection || nav?.mozConnection || nav?.webkitConnection;
40
- };
41
- const shouldWarmupOnCurrentNetwork = ()=>{
42
- const connection = getConnection();
43
- if (connection?.saveData) return false;
44
- if ('string' == typeof connection?.effectiveType && SLOW_EFFECTIVE_TYPES.has(connection.effectiveType)) return false;
45
- return true;
46
- };
47
- const pruneWarmupCache = (now = getWarmupTimestamp())=>{
48
- for (const [key, timestamp] of warmupCache)if (now - timestamp > WARMUP_TTL) warmupCache.delete(key);
49
- };
50
- const runNextWarmup = ()=>{
51
- while(activeWarmups < MAX_CONCURRENT_WARMUPS && warmupQueue.length > 0){
52
- const task = warmupQueue.shift();
53
- if (task.cancelled) continue;
54
- activeWarmups += 1;
55
- task.run().catch(()=>{
56
- warmupCache.delete(task.key);
57
- }).finally(()=>{
58
- activeWarmups -= 1;
59
- runNextWarmup();
60
- });
61
- }
62
- };
63
- const scheduleWarmup = (key, run)=>{
64
- if (!shouldWarmupOnCurrentNetwork()) return ()=>{};
65
- pruneWarmupCache();
66
- if (warmupCache.has(key)) return ()=>{};
67
- warmupCache.set(key, getWarmupTimestamp());
68
- const task = {
69
- key,
70
- run,
71
- cancelled: false
72
- };
73
- warmupQueue.push(task);
74
- runNextWarmup();
75
- return ()=>{
76
- task.cancelled = true;
77
- if (warmupQueue.includes(task)) warmupCache.delete(task.key);
78
- };
79
- };
80
23
  const setRef = (ref, value)=>{
81
24
  if (!ref) return;
82
25
  if ('function' == typeof ref) return void ref(value);
@@ -84,70 +27,65 @@ const setRef = (ref, value)=>{
84
27
  ref.current = value;
85
28
  } catch {}
86
29
  };
87
- const isDataWarmupEnabled = (route)=>{
88
- const handle = route.handle;
89
- return handle?.navigationWarmup?.data !== false;
90
- };
91
- function usePrefetchBehavior(prefetch, preload, theirElementProps) {
92
- const [maybeWarmup, setMaybeWarmup] = react.useState(false);
93
- const [shouldPrefetch, setShouldPrefetch] = react.useState(false);
94
- const [shouldPreload, setShouldPreload] = react.useState(false);
95
- const [viewportElement, setViewportElement] = react.useState(null);
30
+ function usePrefetchBehavior(prefetch, preload, theirElementProps, policy) {
31
+ const [maybePrefetch, setMaybePrefetch] = react.useState(false);
32
+ const [state, setState] = react.useState({
33
+ code: false,
34
+ data: false
35
+ });
36
+ const [element, setElement] = react.useState(null);
37
+ const observerRef = react.useRef(void 0);
96
38
  const { onFocus, onBlur, onMouseEnter, onMouseLeave, onTouchStart } = theirElementProps;
97
39
  react.useEffect(()=>{
98
- if ('render' === prefetch) setShouldPrefetch(true);
99
- if ('render' === preload) setShouldPreload(true);
40
+ if (!policy) return void setState({
41
+ code: 'render' === prefetch,
42
+ data: 'render' === prefetch
43
+ });
44
+ const observer = policy.observe({
45
+ element,
46
+ prefetch,
47
+ preload,
48
+ notify: (next)=>setState((previous)=>previous.code === next.code && previous.data === next.data ? previous : next)
49
+ });
50
+ observerRef.current = observer;
51
+ return ()=>{
52
+ observerRef.current = void 0;
53
+ observer.dispose();
54
+ };
100
55
  }, [
56
+ policy,
101
57
  prefetch,
102
- preload
58
+ preload,
59
+ element
60
+ ]);
61
+ react.useEffect(()=>{
62
+ if (policy || !maybePrefetch) return;
63
+ const timer = setTimeout(()=>setState({
64
+ code: true,
65
+ data: true
66
+ }), 100);
67
+ return ()=>clearTimeout(timer);
68
+ }, [
69
+ policy,
70
+ maybePrefetch
103
71
  ]);
104
72
  const setIntent = ()=>{
105
- if ('intent' === prefetch || 'intent' === preload) setMaybeWarmup(true);
73
+ if (policy) observerRef.current?.onIntent();
74
+ else if ('intent' === prefetch) setMaybePrefetch(true);
106
75
  };
107
76
  const cancelIntent = ()=>{
108
- if ('intent' === prefetch || 'intent' === preload) {
109
- setMaybeWarmup(false);
110
- setShouldPrefetch(false);
111
- setShouldPreload(false);
77
+ if (policy) observerRef.current?.onCancel();
78
+ else if ('intent' === prefetch) {
79
+ setMaybePrefetch(false);
80
+ setState({
81
+ code: false,
82
+ data: false
83
+ });
112
84
  }
113
85
  };
114
- react.useEffect(()=>{
115
- if (maybeWarmup) {
116
- const id = setTimeout(()=>{
117
- if ('intent' === prefetch) setShouldPrefetch(true);
118
- if ('intent' === preload) setShouldPreload(true);
119
- }, INTENT_DELAY);
120
- return ()=>{
121
- clearTimeout(id);
122
- };
123
- }
124
- }, [
125
- maybeWarmup,
126
- prefetch,
127
- preload
128
- ]);
129
- react.useEffect(()=>{
130
- if (!viewportElement || 'viewport' !== prefetch && 'viewport' !== preload || "u" < typeof IntersectionObserver) return;
131
- const observer = new IntersectionObserver((entries)=>{
132
- if (!entries.some((entry)=>entry.isIntersecting)) return;
133
- if ('viewport' === prefetch) setShouldPrefetch(true);
134
- if ('viewport' === preload) setShouldPreload(true);
135
- observer.disconnect();
136
- }, {
137
- rootMargin: VIEWPORT_ROOT_MARGIN
138
- });
139
- observer.observe(viewportElement);
140
- return ()=>{
141
- observer.disconnect();
142
- };
143
- }, [
144
- prefetch,
145
- preload,
146
- viewportElement
147
- ]);
148
86
  return [
149
- shouldPrefetch,
150
- shouldPreload,
87
+ state.data,
88
+ state.code,
151
89
  {
152
90
  onFocus: composeEventHandlers(onFocus, setIntent),
153
91
  onBlur: composeEventHandlers(onBlur, cancelIntent),
@@ -155,7 +93,7 @@ function usePrefetchBehavior(prefetch, preload, theirElementProps) {
155
93
  onMouseLeave: composeEventHandlers(onMouseLeave, cancelIntent),
156
94
  onTouchStart: composeEventHandlers(onTouchStart, setIntent)
157
95
  },
158
- setViewportElement
96
+ setElement
159
97
  ];
160
98
  }
161
99
  async function loadRouteModule(route, routeAssets, chunkLoader) {
@@ -196,7 +134,8 @@ const PrefetchPageLinks = ({ path, includeData })=>{
196
134
  const context = useContext(InternalRuntimeContext);
197
135
  const { routeManifest, routes } = context;
198
136
  const { routeAssets } = routeManifest || {};
199
- const allowNetworkWarmup = shouldWarmupOnCurrentNetwork();
137
+ const policy = context.linkPrefetchPolicy;
138
+ const allowNetworkWarmup = policy?.canWarmup() ?? true;
200
139
  const matches = useMemo(()=>Array.isArray(routes) ? matchRoutes(routes, pathname) : [], [
201
140
  pathname,
202
141
  routes
@@ -216,7 +155,16 @@ const PrefetchPageLinks = ({ path, includeData })=>{
216
155
  const routeAsset = routeId ? routeAssets[routeId] : void 0;
217
156
  const chunkIds = routeAsset?.chunkIds;
218
157
  if (!routeId || !Array.isArray(chunkIds) || 0 === chunkIds.length) return ()=>{};
219
- return scheduleWarmup(getNavigationWarmupCacheKey(context, chunkLoader, getWebpackPublicPath(), `route-module:${routeId}:${chunkIds.join(',')}`), ()=>loadRouteModule(match.route, routeAssets, chunkLoader));
158
+ const run = ()=>loadRouteModule(match.route, routeAssets, chunkLoader);
159
+ if (policy) return policy.schedule({
160
+ runtimeContext: context,
161
+ chunkLoader,
162
+ publicPath: getWebpackPublicPath(),
163
+ key: `route-module:${routeId}:${chunkIds.join(',')}`,
164
+ run
165
+ });
166
+ run().catch(()=>{});
167
+ return ()=>{};
220
168
  });
221
169
  return ()=>{
222
170
  cancellations.forEach((cancel)=>cancel());
@@ -225,6 +173,7 @@ const PrefetchPageLinks = ({ path, includeData })=>{
225
173
  allowNetworkWarmup,
226
174
  chunkLoader,
227
175
  context,
176
+ policy,
228
177
  routeAssetGeneration
229
178
  ]);
230
179
  if (!allowNetworkWarmup || !includeData || !window._SSR_DATA) return null;
@@ -236,10 +185,11 @@ const PrefetchPageLinks = ({ path, includeData })=>{
236
185
  };
237
186
  const PrefetchDataLinks = ({ matches, path, routeManifest })=>{
238
187
  const { pathname, search, hash } = path;
188
+ const policy = useContext(InternalRuntimeContext).linkPrefetchPolicy;
239
189
  const currentMatches = useMatches();
240
190
  const basename = useHref('/');
241
191
  const dataHrefs = useMemo(()=>matches?.filter((match, index)=>{
242
- if (!isDataWarmupEnabled(match.route) || !match.route.loader || 'function' != typeof match.route.loader || 0 === match.route.loader.length) return false;
192
+ if (policy?.allowData(match.route) === false || !match.route.loader || 'function' != typeof match.route.loader || 0 === match.route.loader.length) return false;
243
193
  if (match.route.shouldRevalidate) {
244
194
  const currentUrl = new URL(location.pathname + location.search + location.hash, window.origin);
245
195
  const nextUrl = new URL(pathname + search + hash, window.origin);
@@ -266,16 +216,10 @@ const PrefetchDataLinks = ({ matches, path, routeManifest })=>{
266
216
  children: dataHrefs
267
217
  });
268
218
  };
269
- const normalizePreloadBehavior = (preload, prefetch)=>{
270
- if (false === preload || 'none' === preload) return 'none';
271
- if (void 0 !== preload) return preload;
272
- if ('none' === prefetch) return 'none';
273
- return prefetch;
274
- };
275
- const createPrefetchLink = (Link)=>/*#__PURE__*/ react.forwardRef(({ to, prefetch = DEFAULT_PREFETCH_BEHAVIOR, preload, ...props }, forwardedRef)=>{
219
+ const createPrefetchLink = (Link)=>/*#__PURE__*/ react.forwardRef(({ to, prefetch, preload, ...props }, forwardedRef)=>{
276
220
  const isAbsolute = 'string' == typeof to && ABSOLUTE_URL_REGEX.test(to);
277
- const resolvedPreload = normalizePreloadBehavior(preload, prefetch);
278
- const [shouldPrefetch, shouldPreload, prefetchHandlers, setViewportElement] = usePrefetchBehavior(prefetch, resolvedPreload, props);
221
+ const policy = useContext(InternalRuntimeContext).linkPrefetchPolicy;
222
+ const [shouldPrefetch, shouldPreload, prefetchHandlers, setViewportElement] = usePrefetchBehavior(prefetch, preload, props, policy);
279
223
  const setAnchorRef = react.useCallback((element)=>{
280
224
  setViewportElement(element);
281
225
  setRef(forwardedRef, element);
@@ -7,4 +7,12 @@ const onBeforeCreateRouter = createRouterSyncHook();
7
7
  const onAfterCreateRouter = createRouterSyncHook();
8
8
  const onBeforeHydrateRouter = createRouterSyncHook();
9
9
  const onAfterHydrateRouter = createRouterSyncHook();
10
- export { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter };
10
+ const routerProviderRegistryHooks = {
11
+ modifyRoutes: modifyRoutes,
12
+ onBeforeCreateRoutes: onBeforeCreateRoutes,
13
+ onBeforeCreateRouter: onBeforeCreateRouter,
14
+ onAfterCreateRouter: onAfterCreateRouter,
15
+ onBeforeHydrateRouter: onBeforeHydrateRouter,
16
+ onAfterHydrateRouter: onAfterHydrateRouter
17
+ };
18
+ export { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter, routerProviderRegistryHooks };
@@ -1,35 +1,4 @@
1
1
  import "node:module";
2
- import { merge } from "@modern-js/runtime-utils/merge";
3
- import { modifyRoutes, routerPlugin } from "./plugin.mjs";
4
- import { createRouterProviderRealm, registerRouterProvider, reportUnsupportedProviderRegistryHooks, resolveRouterProvider, routerProviderRegistryHooks } from "./provider.mjs";
5
- registerRouterProvider('react-router', routerPlugin, {
6
- isDefault: true
7
- });
8
- const createRouterPlugin = (localProviders = [])=>{
9
- const providerRealm = createRouterProviderRealm([
10
- {
11
- name: 'react-router',
12
- factory: routerPlugin,
13
- isDefault: true
14
- },
15
- ...localProviders
16
- ]);
17
- return (userConfig = {})=>({
18
- name: '@modern-js/plugin-router',
19
- registryHooks: routerProviderRegistryHooks,
20
- setup: (api)=>{
21
- const mergedConfig = merge(api.getRuntimeConfig().router || {}, userConfig);
22
- const pluginFactory = resolveRouterProvider(mergedConfig.framework, {
23
- realm: providerRealm
24
- });
25
- const providerPlugin = pluginFactory(userConfig);
26
- reportUnsupportedProviderRegistryHooks(providerPlugin);
27
- providerPlugin.setup?.(api);
28
- }
29
- });
30
- };
31
- const internal_routerPlugin = createRouterPlugin();
32
- const internal = internal_routerPlugin;
2
+ export { routerProviderRegistryHooks } from "./hooks.mjs";
3
+ export { modifyRoutes, routerPlugin as default, routerPlugin } from "./plugin.mjs";
33
4
  export { renderRoutes } from "./utils.mjs";
34
- export default internal;
35
- export { createRouterPlugin, createRouterProviderRealm, internal_routerPlugin as routerPlugin, modifyRoutes, registerRouterProvider, resolveRouterProvider };