@modern-js/runtime 2.60.7-alpha.0 → 2.62.0

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 (49) hide show
  1. package/dist/cjs/core/server/requestHandler.js +2 -0
  2. package/dist/cjs/core/server/stream/afterTemplate.js +9 -5
  3. package/dist/cjs/core/server/string/ssrData.js +1 -1
  4. package/dist/cjs/core/server/utils.js +8 -0
  5. package/dist/cjs/document/Script.js +9 -3
  6. package/dist/cjs/document/cli/index.js +2 -2
  7. package/dist/cjs/document/constants.js +6 -0
  8. package/dist/cjs/router/cli/code/templates.js +2 -2
  9. package/dist/cjs/router/runtime/DeferredDataScripts.node.js +40 -18
  10. package/dist/cjs/router/runtime/constants.js +13 -0
  11. package/dist/cjs/router/runtime/plugin.js +0 -7
  12. package/dist/cjs/router/runtime/plugin.node.js +4 -3
  13. package/dist/esm/core/server/requestHandler.js +3 -1
  14. package/dist/esm/core/server/stream/afterTemplate.js +6 -2
  15. package/dist/esm/core/server/string/ssrData.js +2 -2
  16. package/dist/esm/core/server/utils.js +8 -0
  17. package/dist/esm/document/Script.js +13 -5
  18. package/dist/esm/document/cli/index.js +4 -4
  19. package/dist/esm/document/constants.js +4 -0
  20. package/dist/esm/router/cli/code/templates.js +2 -2
  21. package/dist/esm/router/runtime/DeferredDataScripts.node.js +40 -20
  22. package/dist/esm/router/runtime/constants.js +9 -0
  23. package/dist/esm/router/runtime/plugin.js +0 -7
  24. package/dist/esm/router/runtime/plugin.node.js +4 -3
  25. package/dist/esm-node/core/server/requestHandler.js +3 -1
  26. package/dist/esm-node/core/server/stream/afterTemplate.js +8 -4
  27. package/dist/esm-node/core/server/string/ssrData.js +2 -2
  28. package/dist/esm-node/core/server/utils.js +7 -0
  29. package/dist/esm-node/document/Script.js +11 -5
  30. package/dist/esm-node/document/cli/index.js +3 -3
  31. package/dist/esm-node/document/constants.js +4 -0
  32. package/dist/esm-node/router/cli/code/templates.js +2 -2
  33. package/dist/esm-node/router/runtime/DeferredDataScripts.node.js +40 -18
  34. package/dist/esm-node/router/runtime/constants.js +9 -0
  35. package/dist/esm-node/router/runtime/plugin.js +0 -7
  36. package/dist/esm-node/router/runtime/plugin.node.js +4 -3
  37. package/dist/types/core/context/runtime.d.ts +1 -5
  38. package/dist/types/core/server/stream/afterTemplate.d.ts +1 -1
  39. package/dist/types/core/server/utils.d.ts +1 -0
  40. package/dist/types/core/types.d.ts +1 -0
  41. package/dist/types/document/Script.d.ts +5 -4
  42. package/dist/types/document/constants.d.ts +2 -0
  43. package/dist/types/router/runtime/DeferredDataScripts.node.d.ts +1 -0
  44. package/dist/types/router/runtime/constants.d.ts +34 -0
  45. package/package.json +15 -12
  46. package/scripts/gen-static.ts +26 -0
  47. package/static/modern-inline.js +1 -0
  48. package/static/modern-run-router-data-fn.js +1 -0
  49. package/static/modern-run-window-fn.js +1 -0
@@ -3,10 +3,12 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { serializeJson } from "@modern-js/runtime-utils/node";
4
4
  import { Await, useAsyncError } from "@modern-js/runtime-utils/router";
5
5
  import { Suspense, useEffect, useMemo, useRef } from "react";
6
- import { mergeLoaderDataStr, preResolvedFnStr, resolveFnStr, setupFnStr } from "./constants";
6
+ import { ROUTER_DATA_JSON_ID } from "../../core/constants";
7
+ import { modernInline, runRouterDataFnStr, runWindowFnStr } from "./constants";
7
8
  import { serializeErrors } from "./utils";
8
9
  var DeferredDataScripts = function(props) {
9
10
  var staticContext = props === null || props === void 0 ? void 0 : props.context;
11
+ var inlineScript = props === null || props === void 0 ? void 0 : props.inlineScript;
10
12
  var hydratedRef = useRef(false);
11
13
  useEffect(function() {
12
14
  hydratedRef.current = true;
@@ -20,13 +22,11 @@ var DeferredDataScripts = function(props) {
20
22
  loaderData: staticContext.loaderData,
21
23
  errors: serializeErrors(staticContext.errors)
22
24
  };
23
- var initialScript0 = "_ROUTER_DATA = ".concat(serializeJson(_ROUTER_DATA), ";");
24
- var initialScript1 = [
25
- "_ROUTER_DATA.s = ".concat(setupFnStr),
26
- "_ROUTER_DATA.r = ".concat(resolveFnStr),
27
- "_ROUTER_DATA.p = ".concat(preResolvedFnStr),
28
- mergeLoaderDataStr
29
- ].join("\n");
25
+ var initialScript0 = inlineScript ? "" : "".concat(serializeJson(_ROUTER_DATA));
26
+ var initialScript1 = inlineScript ? [
27
+ "_ROUTER_DATA = ".concat(serializeJson(_ROUTER_DATA), ";"),
28
+ modernInline
29
+ ].join("\n") : modernInline;
30
30
  var deferredDataScripts = [];
31
31
  var initialScripts = Object.entries(activeDeferreds).map(function(param) {
32
32
  var _param = _sliced_to_array(param, 2), routeId = _param[0], deferredData = _param[1];
@@ -79,10 +79,12 @@ var DeferredDataScripts = function(props) {
79
79
  });
80
80
  return {
81
81
  fnName: "mergeLoaderData",
82
+ fnRun: runWindowFnStr,
82
83
  fnArgs: [
83
84
  routeId,
84
85
  deferredKeyPromiseManifests
85
- ]
86
+ ],
87
+ fnScriptSrc: "modern-run-window-fn"
86
88
  };
87
89
  });
88
90
  return [
@@ -99,8 +101,9 @@ var DeferredDataScripts = function(props) {
99
101
  children: [
100
102
  !hydratedRef.current && /* @__PURE__ */ _jsxs(_Fragment, {
101
103
  children: [
102
- /* @__PURE__ */ _jsx("script", {
103
- async: true,
104
+ deferredScripts[0].length !== 0 && /* @__PURE__ */ _jsx("script", {
105
+ type: "application/json",
106
+ id: ROUTER_DATA_JSON_ID,
104
107
  nonce: props === null || props === void 0 ? void 0 : props.nonce,
105
108
  suppressHydrationWarning: true,
106
109
  dangerouslySetInnerHTML: {
@@ -110,21 +113,23 @@ var DeferredDataScripts = function(props) {
110
113
  /* @__PURE__ */ _jsx("script", {
111
114
  async: true,
112
115
  nonce: props === null || props === void 0 ? void 0 : props.nonce,
116
+ "data-script-src": "modern-inline",
113
117
  suppressHydrationWarning: true,
114
118
  dangerouslySetInnerHTML: {
115
119
  __html: deferredScripts[1]
116
120
  }
117
121
  }),
118
122
  deferredScripts[2].map(function(param) {
119
- var fnName = param.fnName, fnArgs = param.fnArgs;
123
+ var fnName = param.fnName, fnArgs = param.fnArgs, fnRun = param.fnRun, fnScriptSrc = param.fnScriptSrc;
120
124
  return /* @__PURE__ */ _jsx("script", {
121
125
  async: true,
126
+ "data-script-src": fnScriptSrc,
127
+ "data-fn-name": fnName,
128
+ "data-fn-args": JSON.stringify(fnArgs),
122
129
  nonce: props === null || props === void 0 ? void 0 : props.nonce,
123
130
  suppressHydrationWarning: true,
124
131
  dangerouslySetInnerHTML: {
125
- __html: "".concat(fnName, "(").concat(fnArgs.map(function(argv) {
126
- return "".concat(JSON.stringify(argv));
127
- }).join(","), ")")
132
+ __html: fnRun
128
133
  }
129
134
  }, fnName);
130
135
  })
@@ -148,9 +153,16 @@ var DeferredDataScript = function(param) {
148
153
  return /* @__PURE__ */ _jsx("script", {
149
154
  async: true,
150
155
  nonce,
156
+ "data-fn-name": "r",
157
+ "data-script-src": "modern-run-router-data-fn",
158
+ "data-fn-args": "".concat(JSON.stringify([
159
+ routeId,
160
+ dataKey,
161
+ data2
162
+ ])),
151
163
  suppressHydrationWarning: true,
152
164
  dangerouslySetInnerHTML: {
153
- __html: "_ROUTER_DATA.r(".concat(JSON.stringify(routeId), ", ").concat(JSON.stringify(dataKey), ", ").concat(serializeJson(data2), ");")
165
+ __html: runRouterDataFnStr
154
166
  }
155
167
  });
156
168
  }
@@ -161,13 +173,21 @@ var ErrorDeferredDataScript = function(param) {
161
173
  var routeId = param.routeId, dataKey = param.dataKey, nonce = param.nonce;
162
174
  var error = useAsyncError();
163
175
  return /* @__PURE__ */ _jsx("script", {
176
+ "data-fn-name": "r",
177
+ "data-script-src": "modern-run-router-data-fn",
178
+ "data-fn-args": "".concat(JSON.stringify([
179
+ routeId,
180
+ dataKey,
181
+ void 0,
182
+ {
183
+ message: error.message,
184
+ stack: error.stack
185
+ }
186
+ ])),
164
187
  nonce,
165
188
  suppressHydrationWarning: true,
166
189
  dangerouslySetInnerHTML: {
167
- __html: "_ROUTER_DATA.r(".concat(JSON.stringify(routeId), ", ").concat(JSON.stringify(dataKey), ", ").concat(void 0, ", ").concat(serializeJson({
168
- message: error.message,
169
- stack: error.stack
170
- }), ");")
190
+ __html: runRouterDataFnStr
171
191
  }
172
192
  });
173
193
  };
@@ -1,10 +1,19 @@
1
+ import { ROUTER_DATA_JSON_ID } from "../../core/constants";
1
2
  var setupFnStr = "function s(r,e){_ROUTER_DATA.r=_ROUTER_DATA.r||{},_ROUTER_DATA.r[r]=_ROUTER_DATA.r[r]||{};return new Promise((function(A,R){_ROUTER_DATA.r[r][e]={resolve:A,reject:R}}))};";
2
3
  var resolveFnStr = "function r(e,r,o,A){A?_ROUTER_DATA.r[e][r].reject(A):_ROUTER_DATA.r[e][r].resolve(o)};";
3
4
  var preResolvedFnStr = "function p(e,r){return void 0!==r?Promise.reject(new Error(r.message)):Promise.resolve(e)};";
4
5
  var mergeLoaderDataStr = 'function mergeLoaderData(e,n){const r=n.reduce((function(e,{key:n,routerDataFnName:r,routerDataFnArgs:a}){const t=a.map((e=>{if("undefined"!==e&&null!==e)return JSON.parse(e)}));return console.info("args",t),{...e,[n]:_ROUTER_DATA[r](...t)}}),{});Object.assign(_ROUTER_DATA.loaderData[e],r)}';
6
+ var initRouterDataAttrs = "_ROUTER_DATA.s = ".concat(setupFnStr, "_ROUTER_DATA.r = ").concat(resolveFnStr, "_ROUTER_DATA.p = ").concat(preResolvedFnStr).concat(mergeLoaderDataStr);
7
+ var modernInline = `function runWindowFn(){window[document.currentScript.getAttribute("data-fn-name")](...JSON.parse(document.currentScript.getAttribute("data-fn-args")))}function runRouterDataFn(){_ROUTER_DATA[document.currentScript.getAttribute("data-fn-name")](...JSON.parse(document.currentScript.getAttribute("data-fn-args")))}function initRouterData(e){var r=document.getElementById(e);if(r)try{_ROUTER_DATA=JSON.parse(r.textContent)}catch(r){console.error("parse ".concat(e," error"),t),_ROUTER_DATA={}}};initRouterData('`.concat(ROUTER_DATA_JSON_ID, "');").concat(initRouterDataAttrs);
8
+ var runRouterDataFnStr = "runRouterDataFn();";
9
+ var runWindowFnStr = "runWindowFn();";
5
10
  export {
11
+ initRouterDataAttrs,
6
12
  mergeLoaderDataStr,
13
+ modernInline,
7
14
  preResolvedFnStr,
8
15
  resolveFnStr,
16
+ runRouterDataFnStr,
17
+ runWindowFnStr,
9
18
  setupFnStr
10
19
  };
@@ -102,13 +102,6 @@ var routerPlugin = function() {
102
102
  };
103
103
  return originSubscribe(wrapedListener);
104
104
  };
105
- Object.defineProperty(runtimeContext, "remixRouter", {
106
- get: function get() {
107
- return router;
108
- },
109
- configurable: true,
110
- enumerable: true
111
- });
112
105
  return router;
113
106
  }, [
114
107
  finalRouteConfig,
@@ -103,8 +103,8 @@ var routerPlugin = function() {
103
103
  throw routerContext.errors[0];
104
104
  }
105
105
  router = createStaticRouter(routes, routerContext);
106
- context.remixRouter = router;
107
106
  context.routerContext = routerContext;
107
+ context.remixRouter = router;
108
108
  context.routes = routes;
109
109
  return [
110
110
  2
@@ -121,7 +121,7 @@ var routerPlugin = function() {
121
121
  return function() {
122
122
  var context = useContext(RuntimeReactContext);
123
123
  var remixRouter = context.remixRouter, routerContext = context.routerContext, ssrContext = context.ssrContext;
124
- var nonce = ssrContext.nonce, mode = ssrContext.mode;
124
+ var nonce = ssrContext.nonce, mode = ssrContext.mode, inlineScript = ssrContext.inlineScript;
125
125
  var routerWrapper = /* @__PURE__ */ _jsxs(_Fragment, {
126
126
  children: [
127
127
  /* @__PURE__ */ _jsx(StaticRouterProvider, {
@@ -133,7 +133,8 @@ var routerPlugin = function() {
133
133
  // So we can inject it only when streaming ssr
134
134
  /* @__PURE__ */ _jsx(DeferredDataScripts, {
135
135
  nonce,
136
- context: routerContext
136
+ context: routerContext,
137
+ inlineScript
137
138
  }),
138
139
  mode === "stream" && JSX_SHELL_STREAM_END_MARK
139
140
  ]
@@ -5,7 +5,7 @@ import { createLoaderManager } from "../loader/loaderManager";
5
5
  import { getGlobalRunner } from "../plugin/runner";
6
6
  import { createRoot } from "../react";
7
7
  import { CHUNK_CSS_PLACEHOLDER } from "./constants";
8
- import { getSSRConfigByEntry, getSSRMode } from "./utils";
8
+ import { getSSRConfigByEntry, getSSRInlineScript, getSSRMode } from "./utils";
9
9
  function createSSRContext(request, options) {
10
10
  const { config, loaderContext, onError, onTiming, locals, resource, params, responseProxy, logger, metrics, reporter } = options;
11
11
  const { nonce } = config;
@@ -24,6 +24,7 @@ function createSSRContext(request, options) {
24
24
  }
25
25
  const ssrConfig = getSSRConfigByEntry(entryName, config.ssr, config.ssrByEntries);
26
26
  const ssrMode = getSSRMode(ssrConfig);
27
+ const inlineScript = getSSRInlineScript(ssrConfig);
27
28
  const loaderFailureMode = typeof ssrConfig === "object" ? ssrConfig.loaderFailureMode : void 0;
28
29
  return {
29
30
  nonce,
@@ -56,6 +57,7 @@ function createSSRContext(request, options) {
56
57
  },
57
58
  reporter,
58
59
  mode: ssrMode,
60
+ inlineScript,
59
61
  onError,
60
62
  onTiming,
61
63
  loaderFailureMode
@@ -1,7 +1,8 @@
1
1
  import { serializeJson } from "@modern-js/runtime-utils/node";
2
+ import { SSR_DATA_JSON_ID } from "../../constants";
2
3
  import { SSR_DATA_PLACEHOLDER } from "../constants";
3
4
  import { buildHtml } from "../shared";
4
- import { attributesToString, safeReplace } from "../utils";
5
+ import { attributesToString, getSSRInlineScript, safeReplace } from "../utils";
5
6
  function buildShellAfterTemplate(afterAppTemplate, options) {
6
7
  const { request, config, ssrConfig, runtimeContext, renderLevel, entryName } = options;
7
8
  const callbacks = [
@@ -63,9 +64,12 @@ function createReplaceSSRData(options) {
63
64
  const attrsStr = attributesToString({
64
65
  nonce
65
66
  });
66
- const ssrDataScript = `
67
- <script${attrsStr}>window._SSR_DATA = ${serializeJson(ssrData)}</script>
68
- `;
67
+ const inlineScript = getSSRInlineScript(ssrConfig);
68
+ const useInlineScript = inlineScript !== false;
69
+ const serializeSSRData = serializeJson(ssrData);
70
+ const ssrDataScript = useInlineScript ? `
71
+ <script${attrsStr}>window._SSR_DATA = ${serializeSSRData}</script>
72
+ ` : `<script type="application/json" id="${SSR_DATA_JSON_ID}">${serializeSSRData}</script>`;
69
73
  return (template) => safeReplace(template, SSR_DATA_PLACEHOLDER, ssrDataScript);
70
74
  }
71
75
  export {
@@ -5,7 +5,7 @@ import { _ as _class_private_method_get } from "@swc/helpers/_/_class_private_me
5
5
  import { _ as _class_private_method_init } from "@swc/helpers/_/_class_private_method_init";
6
6
  import { serializeJson } from "@modern-js/runtime-utils/node";
7
7
  import { ROUTER_DATA_JSON_ID, SSR_DATA_JSON_ID } from "../../constants";
8
- import { attributesToString, serializeErrors } from "../utils";
8
+ import { attributesToString, getSSRInlineScript, serializeErrors } from "../utils";
9
9
  var _options = /* @__PURE__ */ new WeakMap(), _getSSRData = /* @__PURE__ */ new WeakSet(), _getSSRDataScripts = /* @__PURE__ */ new WeakSet();
10
10
  class SSRDataCollector {
11
11
  effect() {
@@ -56,7 +56,7 @@ function getSSRData() {
56
56
  }
57
57
  function getSSRDataScripts(ssrData, routerData) {
58
58
  const { nonce, ssrConfig } = _class_private_field_get(this, _options);
59
- const inlineScript = typeof ssrConfig === "boolean" ? true : (ssrConfig === null || ssrConfig === void 0 ? void 0 : ssrConfig.inlineScript) !== false;
59
+ const inlineScript = getSSRInlineScript(ssrConfig);
60
60
  const useInlineScript = inlineScript !== false;
61
61
  const serializeSSRData = serializeJson(ssrData);
62
62
  const attrsStr = attributesToString({
@@ -47,10 +47,17 @@ function getSSRMode(ssrConfig) {
47
47
  }
48
48
  return (ssrConfig === null || ssrConfig === void 0 ? void 0 : ssrConfig.mode) === "stream" ? "stream" : "string";
49
49
  }
50
+ function getSSRInlineScript(ssrConfig) {
51
+ if (typeof ssrConfig === "object") {
52
+ return ssrConfig.inlineScript === void 0 ? true : ssrConfig.inlineScript;
53
+ }
54
+ return true;
55
+ }
50
56
  export {
51
57
  attributesToString,
52
58
  checkIsNode,
53
59
  getSSRConfigByEntry,
60
+ getSSRInlineScript,
54
61
  getSSRMode,
55
62
  safeReplace,
56
63
  serializeErrors
@@ -1,12 +1,18 @@
1
- import { jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { DOCUMENT_SCRIPT_PLACEHOLDER_END, DOCUMENT_SCRIPT_PLACEHOLDER_START } from "./constants";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { renderToString } from "react-dom/server";
3
+ import { DOCUMENT_SCRIPT_ATTRIBUTES_END, DOCUMENT_SCRIPT_ATTRIBUTES_START, DOCUMENT_SCRIPT_PLACEHOLDER_END, DOCUMENT_SCRIPT_PLACEHOLDER_START } from "./constants";
3
4
  function Script(props) {
4
- const { content } = props;
5
- const contentStr = content.toString();
6
- const contentIIFE = encodeURIComponent(`(${contentStr})()`);
5
+ const { content, ...rests } = props;
6
+ const contentStr = content === null || content === void 0 ? void 0 : content.toString();
7
+ const contentIIFE = (contentStr === null || contentStr === void 0 ? void 0 : contentStr.length) ? encodeURIComponent(`(${contentStr})()`) : "";
8
+ const scriptProperties = renderToString(/* @__PURE__ */ _jsx("script", {
9
+ ...rests
10
+ }));
11
+ const scriptpPropertiesStr = encodeURIComponent(scriptProperties.replace("<script ", "").replace("></script>", ""));
7
12
  return /* @__PURE__ */ _jsxs(_Fragment, {
8
13
  children: [
9
14
  `${DOCUMENT_SCRIPT_PLACEHOLDER_START}`,
15
+ `${DOCUMENT_SCRIPT_ATTRIBUTES_START}${scriptpPropertiesStr}${DOCUMENT_SCRIPT_ATTRIBUTES_END}`,
10
16
  `${contentIIFE}`,
11
17
  `${DOCUMENT_SCRIPT_PLACEHOLDER_END}`
12
18
  ]
@@ -4,7 +4,7 @@ import { build } from "esbuild";
4
4
  import React from "react";
5
5
  import ReactDomServer from "react-dom/server";
6
6
  import { DocumentContext } from "../DocumentContext";
7
- import { BODY_PARTICALS_SEPARATOR, DOCUMENT_CHUNKSMAP_PLACEHOLDER, DOCUMENT_COMMENT_PLACEHOLDER_END, DOCUMENT_COMMENT_PLACEHOLDER_START, DOCUMENT_FILE_NAME, DOCUMENT_LINKS_PLACEHOLDER, DOCUMENT_META_PLACEHOLDER, DOCUMENT_SCRIPTS_PLACEHOLDER, DOCUMENT_SCRIPT_PLACEHOLDER_END, DOCUMENT_SCRIPT_PLACEHOLDER_START, DOCUMENT_SSRDATASCRIPT_PLACEHOLDER, DOCUMENT_SSR_PLACEHOLDER, DOCUMENT_STYLE_PLACEHOLDER_END, DOCUMENT_STYLE_PLACEHOLDER_START, DOCUMENT_TITLE_PLACEHOLDER, DOC_EXT, HEAD_PARTICALS_SEPARATOR, HTML_SEPARATOR, PLACEHOLDER_REPLACER_MAP, TOP_PARTICALS_SEPARATOR } from "../constants";
7
+ import { BODY_PARTICALS_SEPARATOR, DOCUMENT_CHUNKSMAP_PLACEHOLDER, DOCUMENT_COMMENT_PLACEHOLDER_END, DOCUMENT_COMMENT_PLACEHOLDER_START, DOCUMENT_FILE_NAME, DOCUMENT_LINKS_PLACEHOLDER, DOCUMENT_META_PLACEHOLDER, DOCUMENT_SCRIPTS_PLACEHOLDER, DOCUMENT_SCRIPT_ATTRIBUTES_END, DOCUMENT_SCRIPT_ATTRIBUTES_START, DOCUMENT_SCRIPT_PLACEHOLDER_END, DOCUMENT_SCRIPT_PLACEHOLDER_START, DOCUMENT_SSRDATASCRIPT_PLACEHOLDER, DOCUMENT_SSR_PLACEHOLDER, DOCUMENT_STYLE_PLACEHOLDER_END, DOCUMENT_STYLE_PLACEHOLDER_START, DOCUMENT_TITLE_PLACEHOLDER, DOC_EXT, HEAD_PARTICALS_SEPARATOR, HTML_SEPARATOR, PLACEHOLDER_REPLACER_MAP, TOP_PARTICALS_SEPARATOR } from "../constants";
8
8
  const debug = createDebugger("html_genarate");
9
9
  const getDocumenByEntryName = function(entrypoints, entryName, fallbackDir) {
10
10
  var _entrypoints_find;
@@ -134,9 +134,9 @@ const documentPlugin = () => ({
134
134
  ].join("");
135
135
  const titles = htmlWebpackPlugin.tags.headTags.filter((item) => item.tagName === "title").join("").replace("<title>", "").replace("</title>", "") || templateParameters.title;
136
136
  if (html.includes(DOCUMENT_SCRIPT_PLACEHOLDER_START) && html.includes(DOCUMENT_SCRIPT_PLACEHOLDER_END)) {
137
- const { nonce } = config.security;
137
+ const { nonce } = config.security || {};
138
138
  const nonceAttr = nonce ? `nonce=${nonce}` : "";
139
- html = html.replace(new RegExp(`${DOCUMENT_SCRIPT_PLACEHOLDER_START}(.*?)${DOCUMENT_SCRIPT_PLACEHOLDER_END}`, "g"), (_scriptStr, $1) => `<script ${nonceAttr}>${decodeURIComponent($1)}</script>`);
139
+ html = html.replace(new RegExp(`${DOCUMENT_SCRIPT_PLACEHOLDER_START}${DOCUMENT_SCRIPT_ATTRIBUTES_START}(.*)${DOCUMENT_SCRIPT_ATTRIBUTES_END}(.*?)${DOCUMENT_SCRIPT_PLACEHOLDER_END}`, "g"), (_scriptStr, $1, $2) => `<script ${decodeURIComponent($1)} ${nonceAttr}>${decodeURIComponent($2)}</script>`);
140
140
  }
141
141
  if (html.includes(DOCUMENT_STYLE_PLACEHOLDER_START) && html.includes(DOCUMENT_STYLE_PLACEHOLDER_END)) {
142
142
  html = html.replace(new RegExp(`${DOCUMENT_STYLE_PLACEHOLDER_START}(.*?)${DOCUMENT_STYLE_PLACEHOLDER_END}`, "g"), (_styleStr, $1) => `<style>${decodeURIComponent($1)}</style>`);
@@ -20,6 +20,8 @@ const DOCUMENT_SCRIPTS_PLACEHOLDER = encodeURIComponent("<!-- chunk scripts plac
20
20
  const DOCUMENT_LINKS_PLACEHOLDER = encodeURIComponent("<!-- chunk links placeholder -->");
21
21
  const DOCUMENT_SCRIPT_PLACEHOLDER_START = encodeURIComponent("<!-- script-start -->");
22
22
  const DOCUMENT_SCRIPT_PLACEHOLDER_END = encodeURIComponent("<!-- script-end -->");
23
+ const DOCUMENT_SCRIPT_ATTRIBUTES_START = encodeURIComponent("<!-- script-scriptpProperties-start -->");
24
+ const DOCUMENT_SCRIPT_ATTRIBUTES_END = encodeURIComponent("<!-- script-scriptpProperties-end -->");
23
25
  const DOCUMENT_STYLE_PLACEHOLDER_START = encodeURIComponent("<!-- style-start -->");
24
26
  const DOCUMENT_STYLE_PLACEHOLDER_END = encodeURIComponent("<!-- style-end -->");
25
27
  const DOCUMENT_COMMENT_PLACEHOLDER_START = encodeURIComponent("<!-- comment-start -->");
@@ -38,6 +40,8 @@ export {
38
40
  DOCUMENT_LINKS_PLACEHOLDER,
39
41
  DOCUMENT_META_PLACEHOLDER,
40
42
  DOCUMENT_SCRIPTS_PLACEHOLDER,
43
+ DOCUMENT_SCRIPT_ATTRIBUTES_END,
44
+ DOCUMENT_SCRIPT_ATTRIBUTES_START,
41
45
  DOCUMENT_SCRIPT_PLACEHOLDER_END,
42
46
  DOCUMENT_SCRIPT_PLACEHOLDER_START,
43
47
  DOCUMENT_SSRDATASCRIPT_PLACEHOLDER,
@@ -174,8 +174,8 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
174
174
  components.push(route._component);
175
175
  component = `component_${components.length - 1}`;
176
176
  } else {
177
- components.push(route._component);
178
- component = `component_${components.length - 1}`;
177
+ lazyImport = `() => import(/* webpackMode: "eager" */ '${route._component}').then(routeModule => handleRouteModule(routeModule, "${route.id}")).catch(handleRouteModuleError) `;
178
+ component = `lazy(${lazyImport})`;
179
179
  }
180
180
  }
181
181
  } else if (route._component) {
@@ -2,10 +2,12 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { serializeJson } from "@modern-js/runtime-utils/node";
3
3
  import { Await, useAsyncError } from "@modern-js/runtime-utils/router";
4
4
  import { Suspense, useEffect, useMemo, useRef } from "react";
5
- import { mergeLoaderDataStr, preResolvedFnStr, resolveFnStr, setupFnStr } from "./constants";
5
+ import { ROUTER_DATA_JSON_ID } from "../../core/constants";
6
+ import { modernInline, runRouterDataFnStr, runWindowFnStr } from "./constants";
6
7
  import { serializeErrors } from "./utils";
7
8
  const DeferredDataScripts = (props) => {
8
9
  const staticContext = props === null || props === void 0 ? void 0 : props.context;
10
+ const inlineScript = props === null || props === void 0 ? void 0 : props.inlineScript;
9
11
  const hydratedRef = useRef(false);
10
12
  useEffect(() => {
11
13
  hydratedRef.current = true;
@@ -19,13 +21,11 @@ const DeferredDataScripts = (props) => {
19
21
  loaderData: staticContext.loaderData,
20
22
  errors: serializeErrors(staticContext.errors)
21
23
  };
22
- const initialScript0 = `_ROUTER_DATA = ${serializeJson(_ROUTER_DATA)};`;
23
- const initialScript1 = [
24
- `_ROUTER_DATA.s = ${setupFnStr}`,
25
- `_ROUTER_DATA.r = ${resolveFnStr}`,
26
- `_ROUTER_DATA.p = ${preResolvedFnStr}`,
27
- mergeLoaderDataStr
28
- ].join("\n");
24
+ const initialScript0 = inlineScript ? "" : `${serializeJson(_ROUTER_DATA)}`;
25
+ const initialScript1 = inlineScript ? [
26
+ `_ROUTER_DATA = ${serializeJson(_ROUTER_DATA)};`,
27
+ modernInline
28
+ ].join("\n") : modernInline;
29
29
  const deferredDataScripts = [];
30
30
  const initialScripts = Object.entries(activeDeferreds).map(([routeId, deferredData]) => {
31
31
  const pendingKeys = new Set(deferredData.pendingKeys);
@@ -77,10 +77,12 @@ const DeferredDataScripts = (props) => {
77
77
  });
78
78
  return {
79
79
  fnName: `mergeLoaderData`,
80
+ fnRun: runWindowFnStr,
80
81
  fnArgs: [
81
82
  routeId,
82
83
  deferredKeyPromiseManifests
83
- ]
84
+ ],
85
+ fnScriptSrc: "modern-run-window-fn"
84
86
  };
85
87
  });
86
88
  return [
@@ -97,8 +99,9 @@ const DeferredDataScripts = (props) => {
97
99
  children: [
98
100
  !hydratedRef.current && /* @__PURE__ */ _jsxs(_Fragment, {
99
101
  children: [
100
- /* @__PURE__ */ _jsx("script", {
101
- async: true,
102
+ deferredScripts[0].length !== 0 && /* @__PURE__ */ _jsx("script", {
103
+ type: "application/json",
104
+ id: ROUTER_DATA_JSON_ID,
102
105
  nonce: props === null || props === void 0 ? void 0 : props.nonce,
103
106
  suppressHydrationWarning: true,
104
107
  dangerouslySetInnerHTML: {
@@ -108,17 +111,21 @@ const DeferredDataScripts = (props) => {
108
111
  /* @__PURE__ */ _jsx("script", {
109
112
  async: true,
110
113
  nonce: props === null || props === void 0 ? void 0 : props.nonce,
114
+ "data-script-src": "modern-inline",
111
115
  suppressHydrationWarning: true,
112
116
  dangerouslySetInnerHTML: {
113
117
  __html: deferredScripts[1]
114
118
  }
115
119
  }),
116
- deferredScripts[2].map(({ fnName, fnArgs }) => /* @__PURE__ */ _jsx("script", {
120
+ deferredScripts[2].map(({ fnName, fnArgs, fnRun, fnScriptSrc }) => /* @__PURE__ */ _jsx("script", {
117
121
  async: true,
122
+ "data-script-src": fnScriptSrc,
123
+ "data-fn-name": fnName,
124
+ "data-fn-args": JSON.stringify(fnArgs),
118
125
  nonce: props === null || props === void 0 ? void 0 : props.nonce,
119
126
  suppressHydrationWarning: true,
120
127
  dangerouslySetInnerHTML: {
121
- __html: `${fnName}(${fnArgs.map((argv) => `${JSON.stringify(argv)}`).join(",")})`
128
+ __html: fnRun
122
129
  }
123
130
  }, fnName))
124
131
  ]
@@ -139,9 +146,16 @@ const DeferredDataScript = ({ data, routeId, dataKey, nonce }) => {
139
146
  children: (data2) => /* @__PURE__ */ _jsx("script", {
140
147
  async: true,
141
148
  nonce,
149
+ "data-fn-name": "r",
150
+ "data-script-src": "modern-run-router-data-fn",
151
+ "data-fn-args": `${JSON.stringify([
152
+ routeId,
153
+ dataKey,
154
+ data2
155
+ ])}`,
142
156
  suppressHydrationWarning: true,
143
157
  dangerouslySetInnerHTML: {
144
- __html: `_ROUTER_DATA.r(${JSON.stringify(routeId)}, ${JSON.stringify(dataKey)}, ${serializeJson(data2)});`
158
+ __html: runRouterDataFnStr
145
159
  }
146
160
  })
147
161
  }) : null
@@ -150,13 +164,21 @@ const DeferredDataScript = ({ data, routeId, dataKey, nonce }) => {
150
164
  const ErrorDeferredDataScript = ({ routeId, dataKey, nonce }) => {
151
165
  const error = useAsyncError();
152
166
  return /* @__PURE__ */ _jsx("script", {
167
+ "data-fn-name": "r",
168
+ "data-script-src": "modern-run-router-data-fn",
169
+ "data-fn-args": `${JSON.stringify([
170
+ routeId,
171
+ dataKey,
172
+ void 0,
173
+ {
174
+ message: error.message,
175
+ stack: error.stack
176
+ }
177
+ ])}`,
153
178
  nonce,
154
179
  suppressHydrationWarning: true,
155
180
  dangerouslySetInnerHTML: {
156
- __html: `_ROUTER_DATA.r(${JSON.stringify(routeId)}, ${JSON.stringify(dataKey)}, ${void 0}, ${serializeJson({
157
- message: error.message,
158
- stack: error.stack
159
- })});`
181
+ __html: runRouterDataFnStr
160
182
  }
161
183
  });
162
184
  };
@@ -1,10 +1,19 @@
1
+ import { ROUTER_DATA_JSON_ID } from "../../core/constants";
1
2
  const setupFnStr = `function s(r,e){_ROUTER_DATA.r=_ROUTER_DATA.r||{},_ROUTER_DATA.r[r]=_ROUTER_DATA.r[r]||{};return new Promise((function(A,R){_ROUTER_DATA.r[r][e]={resolve:A,reject:R}}))};`;
2
3
  const resolveFnStr = `function r(e,r,o,A){A?_ROUTER_DATA.r[e][r].reject(A):_ROUTER_DATA.r[e][r].resolve(o)};`;
3
4
  const preResolvedFnStr = `function p(e,r){return void 0!==r?Promise.reject(new Error(r.message)):Promise.resolve(e)};`;
4
5
  const mergeLoaderDataStr = `function mergeLoaderData(e,n){const r=n.reduce((function(e,{key:n,routerDataFnName:r,routerDataFnArgs:a}){const t=a.map((e=>{if("undefined"!==e&&null!==e)return JSON.parse(e)}));return console.info("args",t),{...e,[n]:_ROUTER_DATA[r](...t)}}),{});Object.assign(_ROUTER_DATA.loaderData[e],r)}`;
6
+ const initRouterDataAttrs = `_ROUTER_DATA.s = ${setupFnStr}_ROUTER_DATA.r = ${resolveFnStr}_ROUTER_DATA.p = ${preResolvedFnStr}${mergeLoaderDataStr}`;
7
+ const modernInline = `function runWindowFn(){window[document.currentScript.getAttribute("data-fn-name")](...JSON.parse(document.currentScript.getAttribute("data-fn-args")))}function runRouterDataFn(){_ROUTER_DATA[document.currentScript.getAttribute("data-fn-name")](...JSON.parse(document.currentScript.getAttribute("data-fn-args")))}function initRouterData(e){var r=document.getElementById(e);if(r)try{_ROUTER_DATA=JSON.parse(r.textContent)}catch(r){console.error("parse ".concat(e," error"),t),_ROUTER_DATA={}}};initRouterData('${ROUTER_DATA_JSON_ID}');${initRouterDataAttrs}`;
8
+ const runRouterDataFnStr = `runRouterDataFn();`;
9
+ const runWindowFnStr = `runWindowFn();`;
5
10
  export {
11
+ initRouterDataAttrs,
6
12
  mergeLoaderDataStr,
13
+ modernInline,
7
14
  preResolvedFnStr,
8
15
  resolveFnStr,
16
+ runRouterDataFnStr,
17
+ runWindowFnStr,
9
18
  setupFnStr
10
19
  };
@@ -93,13 +93,6 @@ const routerPlugin = (userConfig = {}) => {
93
93
  };
94
94
  return originSubscribe(wrapedListener);
95
95
  };
96
- Object.defineProperty(runtimeContext, "remixRouter", {
97
- get() {
98
- return router;
99
- },
100
- configurable: true,
101
- enumerable: true
102
- });
103
96
  return router;
104
97
  }, [
105
98
  finalRouteConfig,
@@ -80,8 +80,8 @@ const routerPlugin = (userConfig = {}) => {
80
80
  throw routerContext.errors[0];
81
81
  }
82
82
  const router = createStaticRouter(routes, routerContext);
83
- context.remixRouter = router;
84
83
  context.routerContext = routerContext;
84
+ context.remixRouter = router;
85
85
  context.routes = routes;
86
86
  },
87
87
  wrapRoot: (App) => {
@@ -92,7 +92,7 @@ const routerPlugin = (userConfig = {}) => {
92
92
  return () => {
93
93
  const context = useContext(RuntimeReactContext);
94
94
  const { remixRouter, routerContext, ssrContext } = context;
95
- const { nonce, mode } = ssrContext;
95
+ const { nonce, mode, inlineScript } = ssrContext;
96
96
  const routerWrapper = /* @__PURE__ */ _jsxs(_Fragment, {
97
97
  children: [
98
98
  /* @__PURE__ */ _jsx(StaticRouterProvider, {
@@ -104,7 +104,8 @@ const routerPlugin = (userConfig = {}) => {
104
104
  // So we can inject it only when streaming ssr
105
105
  /* @__PURE__ */ _jsx(DeferredDataScripts, {
106
106
  nonce,
107
- context: routerContext
107
+ context: routerContext,
108
+ inlineScript
108
109
  }),
109
110
  mode === "stream" && JSX_SHELL_STREAM_END_MARK
110
111
  ]
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import type { Store } from '@modern-js-reduck/store';
3
- import type { Router, StaticHandlerContext } from '@modern-js/runtime-utils/remix-router';
3
+ import type { StaticHandlerContext } from '@modern-js/runtime-utils/remix-router';
4
4
  import type { RouteManifest } from '../../router/runtime/types';
5
5
  import { createLoaderManager } from '../loader/loaderManager';
6
6
  import type { PluginRunner, runtime } from '../plugin';
@@ -14,10 +14,6 @@ interface BaseRuntimeContext {
14
14
  store?: Store;
15
15
  routeManifest: RouteManifest;
16
16
  routerContext?: StaticHandlerContext;
17
- /**
18
- * private method
19
- */
20
- remixRouter?: Router;
21
17
  /**
22
18
  * private
23
19
  */
@@ -1,4 +1,4 @@
1
- import type { RenderLevel } from '../../constants';
1
+ import { type RenderLevel } from '../../constants';
2
2
  import type { RuntimeContext } from '../../context';
3
3
  import type { HandleRequestConfig } from '../requestHandler';
4
4
  import { type SSRConfig } from '../shared';
@@ -17,3 +17,4 @@ export declare function checkIsNode(): boolean;
17
17
  export declare function serializeErrors(errors: StaticHandlerContext['errors']): StaticHandlerContext['errors'];
18
18
  export declare function getSSRConfigByEntry(entryName: string, ssr?: ServerUserConfig['ssr'], ssrByEntries?: ServerUserConfig['ssrByEntries']): import("@modern-js/app-tools").SSR;
19
19
  export declare function getSSRMode(ssrConfig?: SSRConfig): 'string' | 'stream' | false;
20
+ export declare function getSSRInlineScript(ssrConfig?: SSRConfig): boolean;
@@ -52,6 +52,7 @@ export type SSRServerContext = Pick<BaseSSRServerContext, 'redirection' | 'respo
52
52
  loaderFailureMode?: 'clientRender' | 'errorBoundary';
53
53
  onError?: (e: unknown) => void;
54
54
  onTiming?: (name: string, dur: number) => void;
55
+ inlineScript?: boolean;
55
56
  };
56
57
  interface TSSRBaseContext {
57
58
  request: BaseSSRServerContext['request'] & {
@@ -1,4 +1,5 @@
1
- import React from 'react';
2
- export declare function Script(props: {
3
- content: () => void;
4
- }): React.JSX.Element;
1
+ /// <reference types="react" />
2
+ export declare function Script(props: DocumentScriptProps): import("react").JSX.Element;
3
+ export interface DocumentScriptProps extends Omit<React.ScriptHTMLAttributes<HTMLScriptElement>, 'content'> {
4
+ content?: () => void;
5
+ }
@@ -14,6 +14,8 @@ export declare const DOCUMENT_SCRIPTS_PLACEHOLDER: string;
14
14
  export declare const DOCUMENT_LINKS_PLACEHOLDER: string;
15
15
  export declare const DOCUMENT_SCRIPT_PLACEHOLDER_START: string;
16
16
  export declare const DOCUMENT_SCRIPT_PLACEHOLDER_END: string;
17
+ export declare const DOCUMENT_SCRIPT_ATTRIBUTES_START: string;
18
+ export declare const DOCUMENT_SCRIPT_ATTRIBUTES_END: string;
17
19
  export declare const DOCUMENT_STYLE_PLACEHOLDER_START: string;
18
20
  export declare const DOCUMENT_STYLE_PLACEHOLDER_END: string;
19
21
  export declare const DOCUMENT_COMMENT_PLACEHOLDER_START: string;
@@ -6,6 +6,7 @@ import type { StaticHandlerContext } from '@modern-js/runtime-utils/remix-router
6
6
  */
7
7
  declare const DeferredDataScripts: (props?: {
8
8
  nonce?: string;
9
+ inlineScript?: boolean;
9
10
  context: StaticHandlerContext;
10
11
  }) => import("react").JSX.Element | null;
11
12
  export default DeferredDataScripts;