@modern-js/runtime 2.68.0 → 2.68.2

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 (88) hide show
  1. package/dist/cjs/cli/code.js +6 -3
  2. package/dist/cjs/cli/template.js +72 -21
  3. package/dist/cjs/cli/template.server.js +62 -13
  4. package/dist/cjs/core/context/index.js +19 -2
  5. package/dist/cjs/core/context/serverPayload.server.js +40 -0
  6. package/dist/cjs/core/server/requestHandler.js +47 -11
  7. package/dist/cjs/router/cli/code/index.js +13 -6
  8. package/dist/cjs/router/cli/code/templates.js +44 -20
  9. package/dist/cjs/router/cli/handler.js +17 -2
  10. package/dist/cjs/router/cli/index.js +6 -5
  11. package/dist/cjs/router/index.js +0 -21
  12. package/dist/cjs/router/internal.js +30 -0
  13. package/dist/cjs/router/runtime/PrefetchLink.js +3 -4
  14. package/dist/cjs/router/runtime/constants.js +2 -2
  15. package/dist/cjs/router/runtime/index.js +1 -12
  16. package/dist/cjs/router/runtime/internal.js +36 -0
  17. package/dist/cjs/router/runtime/plugin.js +134 -76
  18. package/dist/cjs/router/runtime/plugin.node.js +73 -32
  19. package/dist/cjs/router/runtime/rsc-router.js +322 -0
  20. package/dist/cjs/router/runtime/utils.js +76 -1
  21. package/dist/cjs/rsc/client.js +11 -0
  22. package/dist/cjs/rsc/server.js +40 -0
  23. package/dist/esm/cli/code.js +6 -3
  24. package/dist/esm/cli/template.js +25 -6
  25. package/dist/esm/cli/template.server.js +3 -3
  26. package/dist/esm/core/context/index.js +14 -1
  27. package/dist/esm/core/context/serverPayload.server.js +15 -0
  28. package/dist/esm/core/server/requestHandler.js +102 -9
  29. package/dist/esm/router/cli/code/index.js +12 -6
  30. package/dist/esm/router/cli/code/templates.js +29 -13
  31. package/dist/esm/router/cli/handler.js +33 -6
  32. package/dist/esm/router/cli/index.js +6 -5
  33. package/dist/esm/router/index.js +0 -6
  34. package/dist/esm/router/internal.js +5 -0
  35. package/dist/esm/router/runtime/PrefetchLink.js +2 -2
  36. package/dist/esm/router/runtime/constants.js +2 -2
  37. package/dist/esm/router/runtime/index.js +1 -9
  38. package/dist/esm/router/runtime/internal.js +10 -0
  39. package/dist/esm/router/runtime/plugin.js +134 -85
  40. package/dist/esm/router/runtime/plugin.node.js +110 -40
  41. package/dist/esm/router/runtime/rsc-router.js +437 -0
  42. package/dist/esm/router/runtime/utils.js +95 -1
  43. package/dist/esm/rsc/client.js +6 -0
  44. package/dist/esm/rsc/server.js +86 -0
  45. package/dist/esm-node/cli/code.js +6 -3
  46. package/dist/esm-node/cli/template.js +72 -21
  47. package/dist/esm-node/cli/template.server.js +62 -13
  48. package/dist/esm-node/core/context/index.js +14 -1
  49. package/dist/esm-node/core/context/serverPayload.server.js +15 -0
  50. package/dist/esm-node/core/server/requestHandler.js +45 -9
  51. package/dist/esm-node/router/cli/code/index.js +12 -6
  52. package/dist/esm-node/router/cli/code/templates.js +44 -20
  53. package/dist/esm-node/router/cli/handler.js +17 -2
  54. package/dist/esm-node/router/cli/index.js +6 -5
  55. package/dist/esm-node/router/index.js +0 -6
  56. package/dist/esm-node/router/internal.js +5 -0
  57. package/dist/esm-node/router/runtime/PrefetchLink.js +2 -2
  58. package/dist/esm-node/router/runtime/constants.js +2 -2
  59. package/dist/esm-node/router/runtime/index.js +1 -9
  60. package/dist/esm-node/router/runtime/internal.js +10 -0
  61. package/dist/esm-node/router/runtime/plugin.js +126 -78
  62. package/dist/esm-node/router/runtime/plugin.node.js +75 -34
  63. package/dist/esm-node/router/runtime/rsc-router.js +284 -0
  64. package/dist/esm-node/router/runtime/utils.js +74 -1
  65. package/dist/esm-node/rsc/client.js +6 -0
  66. package/dist/esm-node/rsc/server.js +35 -0
  67. package/dist/types/cli/template.d.ts +4 -2
  68. package/dist/types/cli/template.server.d.ts +2 -1
  69. package/dist/types/common.d.ts +1 -1
  70. package/dist/types/config.d.ts +1 -1
  71. package/dist/types/core/context/index.d.ts +38 -3
  72. package/dist/types/core/context/serverPayload.server.d.ts +3 -0
  73. package/dist/types/core/server/requestHandler.d.ts +1 -1
  74. package/dist/types/index.d.ts +1 -1
  75. package/dist/types/router/cli/code/index.d.ts +1 -0
  76. package/dist/types/router/cli/code/templates.d.ts +4 -2
  77. package/dist/types/router/index.d.ts +0 -2
  78. package/dist/types/router/internal.d.ts +2 -0
  79. package/dist/types/router/runtime/PrefetchLink.d.ts +0 -1
  80. package/dist/types/router/runtime/constants.d.ts +3 -3
  81. package/dist/types/router/runtime/index.d.ts +1 -9
  82. package/dist/types/router/runtime/internal.d.ts +8 -0
  83. package/dist/types/router/runtime/rsc-router.d.ts +14 -0
  84. package/dist/types/router/runtime/utils.d.ts +26 -5
  85. package/dist/types/rsc/client.d.ts +1 -0
  86. package/dist/types/rsc/server.d.ts +1 -0
  87. package/package.json +21 -12
  88. package/static/modern-inline.js +1 -1
@@ -1,7 +1,21 @@
1
1
  import path from "path";
2
2
  import { JS_EXTENSIONS, findExists, formatImportPath } from "@modern-js/utils";
3
3
  import { ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME, ENTRY_POINT_RUNTIME_REGISTER_FILE_NAME } from "./constants";
4
- const genRenderCode = ({ srcDirectory, internalSrcAlias, metaName, entry, customEntry, customBootstrap, mountId, enableRsc }) => {
4
+ const genRenderStatement = ({ customBootstrap, enableRsc, mountId, isNestedRouter }) => {
5
+ if (customBootstrap) {
6
+ return `customBootstrap(ModernRoot, () => render(<ModernRoot />, '${mountId || "root"}'));`;
7
+ }
8
+ if (enableRsc) {
9
+ if (!isNestedRouter) {
10
+ return `render(<ModernRoot>
11
+ <RscClientRoot rscPayload={data} />
12
+ </ModernRoot>, '${mountId || "root"}');`;
13
+ }
14
+ return `render(<ModernRoot rscPayload={data} />, '${mountId || "root"}');`;
15
+ }
16
+ return `render(<ModernRoot />, '${mountId || "root"}');`;
17
+ };
18
+ const genRenderCode = ({ srcDirectory, internalSrcAlias, metaName, entry, customEntry, customBootstrap, mountId, enableRsc, isNestedRouter }) => {
5
19
  if (customEntry) {
6
20
  return `import '${formatImportPath(entry.replace(srcDirectory, internalSrcAlias))}'`;
7
21
  }
@@ -20,11 +34,14 @@ ${customBootstrap ? `import customBootstrap from '${formatImportPath(customBoots
20
34
 
21
35
  const ModernRoot = createRoot();
22
36
 
23
- ${customBootstrap ? `customBootstrap(ModernRoot, () => render(<ModernRoot />, '${mountId || "root"}'));` : enableRsc ? `render(<ModernRoot>
24
- <RscClientRoot data={data} />
25
- </ModernRoot>, '${mountId || "root"}');` : `render(<ModernRoot />, '${mountId || "root"}');`}`;
37
+ ${genRenderStatement({
38
+ customBootstrap,
39
+ enableRsc,
40
+ mountId,
41
+ isNestedRouter
42
+ })}`;
26
43
  };
27
- const entryForCSRWithRSC = ({ metaName, entryName, urlPath = "/", mountId = "root" }) => {
44
+ const entryForCSRWithRSC = ({ metaName, entryName, urlPath = "/", mountId = "root", isNestedRouter }) => {
28
45
  return `
29
46
  import '@${metaName}/runtime/registry/${entryName}';
30
47
  import { render } from '@${metaName}/runtime/browser';
@@ -32,28 +49,61 @@ const entryForCSRWithRSC = ({ metaName, entryName, urlPath = "/", mountId = "roo
32
49
 
33
50
  import {
34
51
  RscClientRoot,
35
- createFromFetch
52
+ createFromFetch,
53
+ isRedirectResponse,
54
+ rscStream,
55
+ callServer,
56
+ createFromReadableStream
36
57
  } from '@${metaName}/runtime/rsc/client';
37
58
 
38
- const content = createFromFetch(
39
- fetch('${urlPath}', {
40
- headers: {
41
- 'x-rsc-tree': 'true',
42
- },
43
- }),
44
- );
59
+ const handleRedirectResponse = (res: Response) => {
60
+ const { headers } = res;
61
+ const location = headers.get('X-Modernjs-Redirect');
62
+ const baseUrl = headers.get('X-Modernjs-BaseUrl');
63
+ if (location) {
64
+ if (baseUrl !== '/') {
65
+ window.location.replace(baseUrl + location);
66
+ } else {
67
+ window.location.replace(location);
68
+ }
69
+ return;
70
+ }
71
+ return res;
72
+ };
73
+
74
+ ${process.env.MODERN_DISABLE_INJECT_RSC_DATA ? `
75
+ const data = createFromFetch(
76
+ fetch(location.pathname, {
77
+ headers: {
78
+ 'x-rsc-tree': 'true',
79
+ },
80
+ }).then(handleRedirectResponse),
81
+ )
82
+ ` : `
83
+ const data = createFromReadableStream(rscStream, {
84
+ callServer: callServer,
85
+ });
86
+ `}
45
87
 
46
88
  const ModernRoot = createRoot();
47
89
 
48
- render(
49
- <ModernRoot>
50
- <RscClientRoot data={content} />
51
- </ModernRoot>,
52
- '${mountId}',
53
- );
90
+ ${isNestedRouter ? `
91
+ render(
92
+ <ModernRoot rscPayload={data}>
93
+ </ModernRoot>,
94
+ '${mountId}',
95
+ );
96
+ ` : `
97
+ render(
98
+ <ModernRoot>
99
+ <RscClientRoot rscPayload={data} />
100
+ </ModernRoot>,
101
+ '${mountId}',
102
+ );
103
+ `}
54
104
  `;
55
105
  };
56
- const index = ({ srcDirectory, internalSrcAlias, metaName, entry, entryName, customEntry, customBootstrap, mountId, enableRsc }) => `import '@${metaName}/runtime/registry/${entryName}';
106
+ const index = ({ srcDirectory, internalSrcAlias, metaName, entry, entryName, customEntry, customBootstrap, mountId, enableRsc, isNestedRouter }) => `import '@${metaName}/runtime/registry/${entryName}';
57
107
  ${genRenderCode({
58
108
  srcDirectory,
59
109
  internalSrcAlias,
@@ -62,7 +112,8 @@ ${genRenderCode({
62
112
  customEntry,
63
113
  customBootstrap,
64
114
  mountId,
65
- enableRsc
115
+ enableRsc,
116
+ isNestedRouter
66
117
  })}
67
118
  `;
68
119
  const register = () => `import './${ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME}';
@@ -24,6 +24,7 @@ import {
24
24
  createRequestHandler,
25
25
  } from '@#metaName/runtime/ssr/server';
26
26
  import { RSCServerSlot } from '@#metaName/runtime/rsc/client';
27
+ import { renderRsc } from '@#metaName/runtime/rsc/server';
27
28
  export { handleAction } from '@#metaName/runtime/rsc/server';
28
29
 
29
30
  const handleRequest = async (request, ServerRoot, options) => {
@@ -34,7 +35,7 @@ const handleRequest = async (request, ServerRoot, options) => {
34
35
  </ServerRoot>,
35
36
  {
36
37
  ...options,
37
- rscRoot: <options.RSCRoot />,
38
+ rscRoot: options.rscRoot,
38
39
  },
39
40
  );
40
41
 
@@ -46,7 +47,22 @@ const handleRequest = async (request, ServerRoot, options) => {
46
47
  };
47
48
 
48
49
  export const requestHandler = createRequestHandler(handleRequest, {
49
- enableRsc: true,
50
+ enableRsc: true
51
+ });
52
+
53
+ const handleRSCRequest = async (request, ServerRoot, options) => {
54
+ const { serverPayload } = options;
55
+ const stream = renderRsc({
56
+ element: options.rscRoot,
57
+ clientManifest: options.rscClientManifest!,
58
+ });
59
+
60
+ return new Response(stream);
61
+ }
62
+
63
+
64
+ export const rscPayloadHandler = createRequestHandler(handleRSCRequest, {
65
+ enableRsc: true
50
66
  });
51
67
  `;
52
68
  const serverIndex = (options) => {
@@ -56,24 +72,57 @@ const serverIndex = (options) => {
56
72
  ${genHandlerCode(options)}
57
73
  `;
58
74
  };
59
- const entryForCSRWithRSC = ({ metaName }) => {
75
+ const entryForCSRWithRSC = ({ metaName, entryName }) => {
60
76
  return `
61
- import App from './AppProxy';
62
- import { renderRsc } from '@${metaName}/runtime/rsc/server'
77
+ import '@${metaName}/runtime/registry/${entryName}';
78
+ import {
79
+ createRequestHandler,
80
+ } from '@${metaName}/runtime/ssr/server';
81
+ import { renderRsc, processRSCStream } from '@${metaName}/runtime/rsc/server'
63
82
  export { handleAction } from '@${metaName}/runtime/rsc/server';
64
83
 
84
+ const handleCSRRender = async (request, ServerRoot, options) => {
85
+ const rscPayloadStream = renderRsc({
86
+ element: options.rscRoot,
87
+ clientManifest: options.rscClientManifest!,
88
+ });
89
+ const stream = new ReadableStream({
90
+ start(controller) {
91
+ const encoder = new TextEncoder();
92
+
93
+ controller.enqueue(encoder.encode(options.html));
65
94
 
66
- export const rscRequestHandler = ({
67
- clientManifest
68
- }) => {
95
+ processRSCStream(rscPayloadStream, controller, encoder)
96
+ .catch(err => {
97
+ controller.error(err);
98
+ });
99
+ }
100
+ });
101
+
102
+ return new Response(stream, {
103
+ status: 200,
104
+ headers: new Headers({
105
+ 'content-type': 'text/html; charset=UTF-8',
106
+ }),
107
+ });
108
+ }
109
+
110
+ export const renderRscStreamHandler = createRequestHandler(handleCSRRender, {
111
+ enableRsc: true
112
+ });
113
+
114
+ const handleRequest = async (request, ServerRoot, options) => {
69
115
  const stream = renderRsc({
70
- element: <App/>,
71
- clientManifest,
72
- })
116
+ element: options.rscRoot,
117
+ clientManifest: options.rscClientManifest!,
118
+ });
73
119
 
74
- const response = new Response(stream);
75
- return response
120
+ return new Response(stream);
76
121
  }
122
+
123
+ export const rscPayloadHandler = createRequestHandler(handleRequest, {
124
+ enableRsc: true
125
+ });
77
126
  `;
78
127
  };
79
128
  function genHandlerCode({ mode, metaName, customServerEntry, srcDirectory, internalSrcAlias, enableRsc }) {
@@ -1,5 +1,12 @@
1
1
  import { RuntimeReactContext, getInitialContext } from "./runtime";
2
2
  const globalContext = {};
3
+ import { getServerPayload, setServerPayload } from "./serverPayload.server";
4
+ function getGlobalIsRscClient() {
5
+ return globalContext.isRscClient;
6
+ }
7
+ function getGlobalEnableRsc() {
8
+ return globalContext.enableRsc;
9
+ }
3
10
  function setGlobalContext(context) {
4
11
  globalContext.entryName = context.entryName;
5
12
  globalContext.App = context.App;
@@ -8,6 +15,8 @@ function setGlobalContext(context) {
8
15
  globalContext.appConfig = typeof context.appConfig === "function" ? context.appConfig() : context.appConfig;
9
16
  globalContext.layoutApp = context.layoutApp;
10
17
  globalContext.RSCRoot = context.RSCRoot;
18
+ globalContext.isRscClient = context.isRscClient;
19
+ globalContext.enableRsc = context.enableRsc;
11
20
  }
12
21
  function getCurrentEntryName() {
13
22
  return globalContext.entryName;
@@ -44,11 +53,15 @@ export {
44
53
  getGlobalApp,
45
54
  getGlobalAppConfig,
46
55
  getGlobalAppInit,
56
+ getGlobalEnableRsc,
47
57
  getGlobalInternalRuntimeContext,
58
+ getGlobalIsRscClient,
48
59
  getGlobalLayoutApp,
49
60
  getGlobalRSCRoot,
50
61
  getGlobalRoutes,
51
62
  getInitialContext,
63
+ getServerPayload,
52
64
  setGlobalContext,
53
- setGlobalInternalRuntimeContext
65
+ setGlobalInternalRuntimeContext,
66
+ setServerPayload
54
67
  };
@@ -0,0 +1,15 @@
1
+ import { storage } from "@modern-js/runtime-utils/node";
2
+ const getServerPayload = () => {
3
+ const context = storage.useContext();
4
+ return context === null || context === void 0 ? void 0 : context.serverPayload;
5
+ };
6
+ const setServerPayload = (payload) => {
7
+ const context = storage.useContext();
8
+ if (context) {
9
+ context.serverPayload = payload;
10
+ }
11
+ };
12
+ export {
13
+ getServerPayload,
14
+ setServerPayload
15
+ };
@@ -1,12 +1,37 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
1
2
  import { storage } from "@modern-js/runtime-utils/node";
2
3
  import { getPathname, parseCookie, parseHeaders, parseQuery } from "@modern-js/runtime-utils/universal/request";
4
+ import { Fragment } from "react";
3
5
  import { getGlobalAppInit, getGlobalInternalRuntimeContext, getGlobalRSCRoot } from "../context";
4
6
  import { getInitialContext } from "../context/runtime";
7
+ import { getServerPayload } from "../context/serverPayload.server";
5
8
  import { createLoaderManager } from "../loader/loaderManager";
6
9
  import { createRoot } from "../react";
7
10
  import { CHUNK_CSS_PLACEHOLDER } from "./constants";
8
11
  import { SSRErrors } from "./tracer";
9
12
  import { getSSRConfigByEntry, getSSRMode } from "./utils";
13
+ async function handleRSCRequest(request, Root, context, options, handleRequest) {
14
+ const serverPayload = getServerPayload();
15
+ if (typeof serverPayload !== "undefined") {
16
+ return await handleRequest(request, Root, {
17
+ ...options,
18
+ runtimeContext: context,
19
+ rscRoot: serverPayload
20
+ });
21
+ }
22
+ const App = getGlobalRSCRoot();
23
+ if (App) {
24
+ return await handleRequest(request, Fragment, {
25
+ ...options,
26
+ runtimeContext: context,
27
+ rscRoot: /* @__PURE__ */ _jsx(App, {})
28
+ });
29
+ }
30
+ return await handleRequest(request, Root, {
31
+ ...options,
32
+ runtimeContext: context
33
+ });
34
+ }
10
35
  function createSSRContext(request, options) {
11
36
  const { config, loaderContext, onError, onTiming, locals, resource, params, responseProxy, logger, metrics, reporter } = options;
12
37
  const { nonce, useJsonScript } = config;
@@ -77,7 +102,8 @@ const createRequestHandler = async (handleRequest, createRequestOptions) => {
77
102
  request,
78
103
  monitors: options.monitors,
79
104
  responseProxy,
80
- activeDeferreds
105
+ activeDeferreds,
106
+ serverPayload: void 0
81
107
  }, async () => {
82
108
  var _context_routerContext, _context_routerContext1, _context_routerContext2;
83
109
  const Root = createRoot();
@@ -135,15 +161,25 @@ const createRequestHandler = async (handleRequest, createRequestOptions) => {
135
161
  context.initialData = initialData;
136
162
  const redirectResponse = getRedirectResponse(initialData);
137
163
  if (redirectResponse) {
138
- return redirectResponse;
164
+ if (createRequestOptions === null || createRequestOptions === void 0 ? void 0 : createRequestOptions.enableRsc) {
165
+ return initialData;
166
+ } else {
167
+ return redirectResponse;
168
+ }
169
+ }
170
+ if (!(createRequestOptions === null || createRequestOptions === void 0 ? void 0 : createRequestOptions.enableRsc)) {
171
+ const { htmlTemplate } = options.resource;
172
+ options.resource.htmlTemplate = htmlTemplate.replace("</head>", `${CHUNK_CSS_PLACEHOLDER}</head>`);
173
+ }
174
+ let response;
175
+ if (createRequestOptions === null || createRequestOptions === void 0 ? void 0 : createRequestOptions.enableRsc) {
176
+ response = await handleRSCRequest(request, Root, context, options, handleRequest);
177
+ } else {
178
+ response = await handleRequest(request, Root, {
179
+ ...options,
180
+ runtimeContext: context
181
+ });
139
182
  }
140
- const { htmlTemplate } = options.resource;
141
- options.resource.htmlTemplate = htmlTemplate.replace("</head>", `${CHUNK_CSS_PLACEHOLDER}</head>`);
142
- const response = await handleRequest(request, Root, {
143
- ...options,
144
- runtimeContext: context,
145
- RSCRoot: (createRequestOptions === null || createRequestOptions === void 0 ? void 0 : createRequestOptions.enableRsc) && getGlobalRSCRoot()
146
- });
147
183
  Object.entries(responseProxy.headers).forEach(([key, value]) => {
148
184
  response.headers.set(key, value);
149
185
  });
@@ -1,5 +1,5 @@
1
1
  import path from "path";
2
- import { fs, getEntryOptions, isSSGEntry, isUseSSRBundle, logger } from "@modern-js/utils";
2
+ import { fs, getEntryOptions, isSSGEntry, isUseRsc, isUseSSRBundle, logger } from "@modern-js/utils";
3
3
  import { filterRoutesForServer, filterRoutesLoader, markRoutes } from "@modern-js/utils";
4
4
  import { cloneDeep } from "@modern-js/utils/lodash";
5
5
  import { ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME } from "../../../cli/constants";
@@ -73,14 +73,15 @@ const generateCode = async (appContext, config, entrypoints, api, isRouterV5) =>
73
73
  code: await templates.fileSystemRoutes({
74
74
  metaName,
75
75
  routes,
76
- ssrMode: useSSG ? "string" : mode,
76
+ ssrMode: useSSG ? "string" : isUseRsc(config2) ? "stream" : mode,
77
77
  nestedRoutesEntry: entrypoint.nestedRoutesEntry,
78
78
  entryName: entrypoint.entryName,
79
79
  internalDirectory,
80
- splitRouteChunks: config2 === null || config2 === void 0 ? void 0 : (_config_output = config2.output) === null || _config_output === void 0 ? void 0 : _config_output.splitRouteChunks
80
+ splitRouteChunks: config2 === null || config2 === void 0 ? void 0 : (_config_output = config2.output) === null || _config_output === void 0 ? void 0 : _config_output.splitRouteChunks,
81
+ isRscClient: isUseRsc(config2)
81
82
  })
82
83
  });
83
- if (entrypoint.nestedRoutesEntry && isUseSSRBundle(config2)) {
84
+ if (entrypoint.nestedRoutesEntry && (isUseSSRBundle(config2) || isUseRsc(config2))) {
84
85
  var _config_output1;
85
86
  const routesServerFile = getServerLoadersFile(internalDirectory, entryName);
86
87
  const filtedRoutesForServer = filterRoutesForServer(routes);
@@ -97,7 +98,8 @@ const generateCode = async (appContext, config, entrypoints, api, isRouterV5) =>
97
98
  nestedRoutesEntry: entrypoint.nestedRoutesEntry,
98
99
  entryName: entrypoint.entryName,
99
100
  internalDirectory,
100
- splitRouteChunks: config2 === null || config2 === void 0 ? void 0 : (_config_output1 = config2.output) === null || _config_output1 === void 0 ? void 0 : _config_output1.splitRouteChunks
101
+ splitRouteChunks: config2 === null || config2 === void 0 ? void 0 : (_config_output1 = config2.output) === null || _config_output1 === void 0 ? void 0 : _config_output1.splitRouteChunks,
102
+ isRscClient: false
101
103
  });
102
104
  await fs.outputFile(path.resolve(internalDirectory, `./${entryName}/routes.server.js`), serverRoutesCode, "utf8");
103
105
  }
@@ -114,7 +116,11 @@ const generateCode = async (appContext, config, entrypoints, api, isRouterV5) =>
114
116
  function generatorRegisterCode(internalDirectory, entryName, code) {
115
117
  fs.outputFileSync(path.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME}.js`), code, "utf8");
116
118
  }
119
+ function generatorServerRegisterCode(internalDirectory, entryName, code) {
120
+ fs.outputFileSync(path.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME}.server.js`), code, "utf8");
121
+ }
117
122
  export {
118
123
  generateCode,
119
- generatorRegisterCode
124
+ generatorRegisterCode,
125
+ generatorServerRegisterCode
120
126
  };
@@ -85,7 +85,7 @@ const routesForServer = ({ routesForServerLoaderMatches }) => {
85
85
  };
86
86
  const createMatchReg = (keyword) => new RegExp(`("${keyword}":\\s)"([^
87
87
  ]+)"`, "g");
88
- const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry, entryName, internalDirectory, splitRouteChunks = true }) => {
88
+ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry, entryName, internalDirectory, splitRouteChunks = true, isRscClient = false }) => {
89
89
  const components = [];
90
90
  const loadings = [];
91
91
  const errors = [];
@@ -111,14 +111,14 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
111
111
  return "";
112
112
  };
113
113
  const createLazyImport = ({ componentPath, routeId, webpackChunkName, eager }) => {
114
- const importOptions = webpackChunkName ? `/* webpackChunkName: "${routeId}" */ ` : eager ? `/* webpackMode: "eager" */ ` : "";
114
+ const importOptions = webpackChunkName ? `/* webpackChunkName: "${routeId}" */ ` : eager ? `/* webpackMode: "eager" */ ` : "";
115
115
  return `() => import(${importOptions}'${componentPath}').then(routeModule => handleRouteModule(routeModule, "${routeId}")).catch(handleRouteModuleError)`;
116
116
  };
117
- const traverseRouteTree = (route) => {
117
+ const traverseRouteTree = (route, isRscClient2) => {
118
118
  let children;
119
119
  if ("children" in route && route.children) {
120
120
  var _route_children;
121
- children = route === null || route === void 0 ? void 0 : (_route_children = route.children) === null || _route_children === void 0 ? void 0 : _route_children.map(traverseRouteTree);
121
+ children = route === null || route === void 0 ? void 0 : (_route_children = route.children) === null || _route_children === void 0 ? void 0 : _route_children.map((child) => traverseRouteTree(child, isRscClient2));
122
122
  }
123
123
  let loading;
124
124
  let error;
@@ -201,7 +201,6 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
201
201
  }
202
202
  const finalRoute = {
203
203
  ...route,
204
- lazyImport,
205
204
  loading,
206
205
  loader,
207
206
  action,
@@ -209,7 +208,10 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
209
208
  error,
210
209
  children
211
210
  };
212
- if (route._component) {
211
+ if (!isRscClient2) {
212
+ finalRoute.lazyImport = lazyImport;
213
+ }
214
+ if (route._component && !isRscClient2) {
213
215
  finalRoute.component = component;
214
216
  }
215
217
  if (route.type === "nested" && route._component && (route.loader || route.data)) {
@@ -222,7 +224,7 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
222
224
  `;
223
225
  for (const route of routes) {
224
226
  if ("type" in route) {
225
- const newRoute = traverseRouteTree(route);
227
+ const newRoute = traverseRouteTree(route, isRscClient);
226
228
  const routeStr = JSON.stringify(newRoute, null, 2);
227
229
  const keywords = [
228
230
  "component",
@@ -321,9 +323,9 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
321
323
  `;
322
324
  return `
323
325
  ${importLazyCode}
324
- ${importComponentsCode}
326
+ ${!isRscClient ? importComponentsCode : ""}
325
327
  ${importRuntimeRouterCode}
326
- ${rootLayoutCode}
328
+ ${!isRscClient ? rootLayoutCode : ""}
327
329
  ${importLoadingCode}
328
330
  ${importErrorComponentsCode}
329
331
  ${importLoadersCode}
@@ -362,7 +364,7 @@ function ssrLoaderCombinedModule(entrypoints, entrypoint, config, appContext) {
362
364
  }
363
365
  return null;
364
366
  }
365
- const runtimeGlobalContext = async ({ entryName, metaName, srcDirectory, nestedRoutesEntry, internalSrcAlias, globalApp }) => {
367
+ const runtimeGlobalContext = async ({ entryName, metaName, srcDirectory, nestedRoutesEntry, internalSrcAlias, globalApp, rscType = false }) => {
366
368
  const imports = [
367
369
  `import { setGlobalContext } from '@${metaName}/runtime/context';`
368
370
  ];
@@ -407,18 +409,40 @@ const runtimeGlobalContext = async ({ entryName, metaName, srcDirectory, nestedR
407
409
  } else {
408
410
  imports.push(`let layoutApp;`);
409
411
  }
410
- return `${imports.join("\n")}
412
+ const isClient = rscType === "client";
413
+ const enableRsc = Boolean(rscType);
414
+ if (isClient) {
415
+ return `${imports.join("\n")}
416
+
417
+ import { routes } from './routes';
418
+
419
+ const entryName = '${entryName}';
420
+ setGlobalContext({
421
+ entryName,
422
+ layoutApp,
423
+ routes,
424
+ appInit,
425
+ appConfig,
426
+ isRscClient: true,
427
+ enableRsc: true,
428
+ });
429
+ `;
430
+ } else {
431
+ return `${imports.join("\n")}
411
432
 
412
- import { routes } from './routes';
433
+ import { routes } from './routes';
413
434
 
414
- const entryName = '${entryName}';
415
- setGlobalContext({
416
- entryName,
417
- layoutApp,
418
- routes,
419
- appInit,
420
- appConfig,
421
- });`;
435
+ const entryName = '${entryName}';
436
+ setGlobalContext({
437
+ entryName,
438
+ layoutApp,
439
+ routes,
440
+ appInit,
441
+ appConfig,
442
+ enableRsc: ${enableRsc},
443
+ });
444
+ `;
445
+ }
422
446
  };
423
447
  export {
424
448
  fileSystemRoutes,
@@ -8,11 +8,13 @@ async function handleModifyEntrypoints(isRouterV5, entrypoints) {
8
8
  return modifyEntrypoints(entrypoints, isRouterV5);
9
9
  }
10
10
  async function handleGeneratorEntryCode(api, entrypoints, isRouterV5) {
11
+ var _resolvedConfig_server;
11
12
  const appContext = api.getAppContext();
12
13
  const { internalDirectory } = appContext;
13
14
  const resolvedConfig = api.getNormalizedConfig();
14
- const { generatorRegisterCode, generateCode } = await import("./code");
15
+ const { generatorRegisterCode, generateCode, generatorServerRegisterCode } = await import("./code");
15
16
  originEntrypoints = cloneDeep(entrypoints);
17
+ const enableRsc = resolvedConfig === null || resolvedConfig === void 0 ? void 0 : (_resolvedConfig_server = resolvedConfig.server) === null || _resolvedConfig_server === void 0 ? void 0 : _resolvedConfig_server.rsc;
16
18
  await generateCode(appContext, resolvedConfig, entrypoints, api, isRouterV5);
17
19
  await Promise.all(entrypoints.map(async (entrypoint) => {
18
20
  if (entrypoint.nestedRoutesEntry || entrypoint.pageRoutesEntry) {
@@ -23,8 +25,21 @@ async function handleGeneratorEntryCode(api, entrypoints, isRouterV5) {
23
25
  srcDirectory: appContext.srcDirectory,
24
26
  nestedRoutesEntry: entrypoint.nestedRoutesEntry,
25
27
  internalSrcAlias: appContext.internalSrcAlias,
26
- globalApp: (_entrypoint_fileSystemRoutes = entrypoint.fileSystemRoutes) === null || _entrypoint_fileSystemRoutes === void 0 ? void 0 : _entrypoint_fileSystemRoutes.globalApp
28
+ globalApp: (_entrypoint_fileSystemRoutes = entrypoint.fileSystemRoutes) === null || _entrypoint_fileSystemRoutes === void 0 ? void 0 : _entrypoint_fileSystemRoutes.globalApp,
29
+ rscType: enableRsc ? "client" : void 0
27
30
  }));
31
+ if (enableRsc) {
32
+ var _entrypoint_fileSystemRoutes1;
33
+ generatorServerRegisterCode(internalDirectory, entrypoint.entryName, await templates.runtimeGlobalContext({
34
+ entryName: entrypoint.entryName,
35
+ metaName: appContext.metaName,
36
+ srcDirectory: appContext.srcDirectory,
37
+ nestedRoutesEntry: entrypoint.nestedRoutesEntry,
38
+ internalSrcAlias: appContext.internalSrcAlias,
39
+ globalApp: (_entrypoint_fileSystemRoutes1 = entrypoint.fileSystemRoutes) === null || _entrypoint_fileSystemRoutes1 === void 0 ? void 0 : _entrypoint_fileSystemRoutes1.globalApp,
40
+ rscType: "server"
41
+ }));
42
+ }
28
43
  }
29
44
  }));
30
45
  return entrypoints;
@@ -25,7 +25,7 @@ const routerPlugin = () => ({
25
25
  if ((nestedRoutesEntry || pageRoutesEntry) && !isRouterV5) {
26
26
  plugins.push({
27
27
  name: "router",
28
- path: `@${metaName2}/runtime/router`,
28
+ path: `@${metaName2}/runtime/router/internal`,
29
29
  config: typeof routerConfig === "boolean" ? {
30
30
  serverBase
31
31
  } : {
@@ -52,9 +52,10 @@ const routerPlugin = () => ({
52
52
  // react-router v6 is no longer support ie 11
53
53
  // so we need to compile these packages to ensure the compatibility
54
54
  // https://github.com/remix-run/react-router/commit/f6df0697e1b2064a2b3a12e8b39577326fdd945b
55
- /node_modules\/react-router/,
56
- /node_modules\/react-router-dom/,
57
- /node_modules\/@remix-run\/router/
55
+ /[\\/]node_modules[\\/]react-router[\\/]/,
56
+ /[\\/]node_modules[\\/]react-router-dom[\\/]/,
57
+ /[\\/]node_modules[\\/]@remix-run[\\/]router[\\/]/,
58
+ path.resolve(__dirname, "../runtime").replace("cjs", "esm")
58
59
  ],
59
60
  globalVars: {
60
61
  "process.env._MODERN_ROUTER_VERSION": "v6"
@@ -75,7 +76,7 @@ const routerPlugin = () => ({
75
76
  const { internalDirectory, metaName: metaName2 } = api.useAppContext();
76
77
  const pluginsExportsUtils = createRuntimeExportsUtils(internalDirectory, "plugins");
77
78
  if (!isRouterV5) {
78
- pluginsExportsUtils.addExport(`export { default as router } from '@${metaName2}/runtime/router'`);
79
+ pluginsExportsUtils.addExport(`export { default as router } from '@${metaName2}/runtime/router/internal'`);
79
80
  }
80
81
  });
81
82
  api.onFileChanged(async (e) => {
@@ -1,7 +1 @@
1
- import { default as default2 } from "./runtime";
2
- import { default as default3 } from "./runtime";
3
1
  export * from "./runtime";
4
- export {
5
- default3 as default,
6
- default2 as router
7
- };
@@ -0,0 +1,5 @@
1
+ export * from "./runtime/internal";
2
+ import { routerPlugin } from "./runtime/internal";
3
+ export {
4
+ routerPlugin as default
5
+ };
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
3
  import { Link as RouterLink, NavLink as RouterNavLink, matchRoutes, useHref, useMatches, useResolvedPath } from "@modern-js/runtime-utils/router";
3
4
  import React, { useContext, useMemo } from "react";
@@ -187,6 +188,5 @@ const NavLink = createPrefetchLink(RouterNavLink);
187
188
  NavLink.displayName = "NavLink";
188
189
  export {
189
190
  Link,
190
- NavLink,
191
- composeEventHandlers
191
+ NavLink
192
192
  };
@@ -2,9 +2,9 @@ import { ROUTER_DATA_JSON_ID } from "../../core/constants";
2
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}}))};`;
3
3
  const resolveFnStr = `function r(e,r,o,A){A?_ROUTER_DATA.r[e][r].reject(A):_ROUTER_DATA.r[e][r].resolve(o)};`;
4
4
  const preResolvedFnStr = `function p(e,r){return void 0!==r?Promise.reject(new Error(r.message)):Promise.resolve(e)};`;
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)}`;
5
+ const mergeLoaderDataStr = `function mergeLoaderData(e,n){var r=n.reduce((function(e,{key:n,routerDataFnName:r,routerDataFnArgs:a}){var 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
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}`;
7
+ const modernInline = `function runWindowFn(){window[document.currentScript.getAttribute("data-fn-name")].apply(window,JSON.parse(document.currentScript.getAttribute("data-fn-args")))}function runRouterDataFn(){_ROUTER_DATA[document.currentScript.getAttribute("data-fn-name")].apply(_ROUTER_DATA,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
8
  const runRouterDataFnStr = `runRouterDataFn();`;
9
9
  const runWindowFnStr = `runWindowFn();`;
10
10
  export {