@modern-js/runtime 2.64.1 → 2.64.3

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 (65) hide show
  1. package/dist/cjs/cli/code.js +67 -28
  2. package/dist/cjs/cli/constants.js +1 -1
  3. package/dist/cjs/cli/ssr/index.js +4 -1
  4. package/dist/cjs/cli/template.js +91 -4
  5. package/dist/cjs/cli/template.server.js +65 -3
  6. package/dist/cjs/core/context/index.js +6 -0
  7. package/dist/cjs/core/server/requestHandler.js +11 -5
  8. package/dist/cjs/core/server/stream/afterTemplate.js +2 -0
  9. package/dist/cjs/core/server/stream/createReadableStream.worker.js +8 -4
  10. package/dist/cjs/core/server/stream/index.js +12 -2
  11. package/dist/cjs/core/server/stream/shared.js +19 -6
  12. package/dist/cjs/core/server/string/index.js +4 -4
  13. package/dist/cjs/core/server/string/prefetch.js +3 -3
  14. package/dist/cjs/core/server/tracer.js +3 -18
  15. package/dist/cjs/router/cli/code/index.js +1 -1
  16. package/dist/cjs/router/cli/code/templates.js +27 -15
  17. package/dist/cjs/rsc/client.js +22 -0
  18. package/dist/cjs/rsc/server.js +22 -0
  19. package/dist/esm/cli/code.js +178 -51
  20. package/dist/esm/cli/constants.js +1 -1
  21. package/dist/esm/cli/ssr/index.js +4 -1
  22. package/dist/esm/cli/template.js +29 -4
  23. package/dist/esm/cli/template.server.js +11 -3
  24. package/dist/esm/core/context/index.js +5 -0
  25. package/dist/esm/core/server/requestHandler.js +12 -6
  26. package/dist/esm/core/server/stream/afterTemplate.js +5 -0
  27. package/dist/esm/core/server/stream/createReadableStream.worker.js +9 -5
  28. package/dist/esm/core/server/stream/index.js +5 -1
  29. package/dist/esm/core/server/stream/shared.js +76 -54
  30. package/dist/esm/core/server/string/index.js +5 -5
  31. package/dist/esm/core/server/string/prefetch.js +3 -3
  32. package/dist/esm/core/server/tracer.js +2 -16
  33. package/dist/esm/router/cli/code/index.js +1 -1
  34. package/dist/esm/router/cli/code/templates.js +29 -16
  35. package/dist/esm/rsc/client.js +1 -0
  36. package/dist/esm/rsc/server.js +1 -0
  37. package/dist/esm-node/cli/code.js +67 -28
  38. package/dist/esm-node/cli/constants.js +1 -1
  39. package/dist/esm-node/cli/ssr/index.js +4 -1
  40. package/dist/esm-node/cli/template.js +87 -4
  41. package/dist/esm-node/cli/template.server.js +64 -3
  42. package/dist/esm-node/core/context/index.js +5 -0
  43. package/dist/esm-node/core/server/requestHandler.js +12 -6
  44. package/dist/esm-node/core/server/stream/afterTemplate.js +2 -0
  45. package/dist/esm-node/core/server/stream/createReadableStream.worker.js +8 -4
  46. package/dist/esm-node/core/server/stream/index.js +1 -1
  47. package/dist/esm-node/core/server/stream/shared.js +20 -7
  48. package/dist/esm-node/core/server/string/index.js +5 -5
  49. package/dist/esm-node/core/server/string/prefetch.js +3 -3
  50. package/dist/esm-node/core/server/tracer.js +2 -15
  51. package/dist/esm-node/router/cli/code/index.js +1 -1
  52. package/dist/esm-node/router/cli/code/templates.js +27 -15
  53. package/dist/esm-node/rsc/client.js +1 -0
  54. package/dist/esm-node/rsc/server.js +1 -0
  55. package/dist/types/cli/constants.d.ts +1 -1
  56. package/dist/types/cli/template.d.ts +20 -1
  57. package/dist/types/cli/template.server.d.ts +4 -0
  58. package/dist/types/core/context/index.d.ts +5 -0
  59. package/dist/types/core/server/requestHandler.d.ts +3 -1
  60. package/dist/types/core/server/stream/shared.d.ts +8 -2
  61. package/dist/types/core/server/tracer.d.ts +3 -5
  62. package/dist/types/core/types.d.ts +3 -2
  63. package/dist/types/rsc/client.d.ts +1 -0
  64. package/dist/types/rsc/server.d.ts +1 -0
  65. package/package.json +29 -12
@@ -1,19 +1,59 @@
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 }) => {
4
+ const genRenderCode = ({ srcDirectory, internalSrcAlias, metaName, entry, customEntry, customBootstrap, mountId, enableRsc }) => {
5
5
  if (customEntry) {
6
6
  return `import '${formatImportPath(entry.replace(srcDirectory, internalSrcAlias))}'`;
7
7
  }
8
8
  return `import { createRoot } from '@${metaName}/runtime/react';
9
9
  import { render } from '@${metaName}/runtime/browser';
10
+
11
+ ${enableRsc ? `import { RscClientRoot, createFromReadableStream, rscStream, callServer } from '@${metaName}/runtime/rsc/client';` : ""}
12
+
13
+ ${enableRsc ? `const data = createFromReadableStream(rscStream, {
14
+ callServer: callServer,
15
+ });` : ""}
16
+
10
17
  ${customBootstrap ? `import customBootstrap from '${formatImportPath(customBootstrap.replace(srcDirectory, internalSrcAlias))}';` : ""}
11
18
 
19
+
20
+
12
21
  const ModernRoot = createRoot();
13
22
 
14
- ${customBootstrap ? `customBootstrap(ModernRoot, () => render(<ModernRoot />, '${mountId || "root"}'));` : `render(<ModernRoot />, '${mountId || "root"}');`}`;
23
+ ${customBootstrap ? `customBootstrap(ModernRoot, () => render(<ModernRoot />, '${mountId || "root"}'));` : enableRsc ? `render(<ModernRoot>
24
+ <RscClientRoot data={data} />
25
+ </ModernRoot>, '${mountId || "root"}');` : `render(<ModernRoot />, '${mountId || "root"}');`}`;
26
+ };
27
+ const entryForCSRWithRSC = ({ metaName, entryName, urlPath = "/", mountId = "root" }) => {
28
+ return `
29
+ import '@${metaName}/runtime/registry/${entryName}';
30
+ import { render } from '@${metaName}/runtime/browser';
31
+ import { createRoot } from '@${metaName}/runtime/react';
32
+
33
+ import {
34
+ RscClientRoot,
35
+ createFromFetch
36
+ } from '@${metaName}/runtime/rsc/client';
37
+
38
+ const content = createFromFetch(
39
+ fetch('${urlPath}', {
40
+ headers: {
41
+ 'x-rsc-tree': 'true',
42
+ },
43
+ }),
44
+ );
45
+
46
+ const ModernRoot = createRoot();
47
+
48
+ render(
49
+ <ModernRoot>
50
+ <RscClientRoot data={content} />
51
+ </ModernRoot>,
52
+ '${mountId}',
53
+ );
54
+ `;
15
55
  };
16
- const index = ({ srcDirectory, internalSrcAlias, metaName, entry, entryName, customEntry, customBootstrap, mountId }) => `import '@${metaName}/runtime/registry/${entryName}';
56
+ const index = ({ srcDirectory, internalSrcAlias, metaName, entry, entryName, customEntry, customBootstrap, mountId, enableRsc }) => `import '@${metaName}/runtime/registry/${entryName}';
17
57
  ${genRenderCode({
18
58
  srcDirectory,
19
59
  internalSrcAlias,
@@ -21,7 +61,8 @@ ${genRenderCode({
21
61
  entry,
22
62
  customEntry,
23
63
  customBootstrap,
24
- mountId
64
+ mountId,
65
+ enableRsc
25
66
  })}
26
67
  `;
27
68
  const register = () => `import './${ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME}';
@@ -59,9 +100,51 @@ setGlobalContext({
59
100
  App,
60
101
  });`;
61
102
  };
103
+ const runtimeGlobalContextForRSCServer = ({ metaName }) => {
104
+ return `
105
+ import { createElement, Fragment } from 'react';
106
+ import { setGlobalContext } from '@${metaName}/runtime/context';
107
+ import AppProxy from './AppProxy';
108
+
109
+ const DefaultRoot = ({ children }: { children?: ReactNode }) =>
110
+ createElement(Fragment, null, children);
111
+
112
+
113
+ setGlobalContext({
114
+ App: DefaultRoot,
115
+ RSCRoot: AppProxy,
116
+ });`;
117
+ };
118
+ const runtimeGlobalContextForRSCClient = ({ metaName }) => {
119
+ return `
120
+ import { createElement, Fragment } from 'react';
121
+ import { setGlobalContext } from '@${metaName}/runtime/context';
122
+
123
+ const DefaultRoot = ({ children }: { children?: ReactNode }) =>
124
+ createElement(Fragment, null, children);
125
+
126
+ setGlobalContext({
127
+ App: DefaultRoot
128
+ });`;
129
+ };
130
+ const AppProxyForRSC = ({ srcDirectory, internalSrcAlias, entry, customEntry }) => {
131
+ return `
132
+ import App from '${// We need to get the path of App.tsx here, but the entry is `src/entry.tsx`
133
+ formatImportPath(customEntry ? entry.replace(/entry\.[tj]sx/, "App").replace(srcDirectory, internalSrcAlias) : entry.replace(srcDirectory, internalSrcAlias).replace(".tsx", ""))}';
134
+ import React from 'react';
135
+
136
+ export default function Root() {
137
+ return React.createElement(App, null);
138
+ }
139
+ `;
140
+ };
62
141
  export {
142
+ AppProxyForRSC,
143
+ entryForCSRWithRSC,
63
144
  index,
64
145
  register,
65
146
  runtimeGlobalContext,
147
+ runtimeGlobalContextForRSCClient,
148
+ runtimeGlobalContextForRSCServer,
66
149
  runtimeRegister
67
150
  };
@@ -19,6 +19,38 @@ const handleRequest = async (request, ServerRoot, options) => {
19
19
 
20
20
  export const requestHandler = createRequestHandler(handleRequest);
21
21
  `;
22
+ const SERVER_ENTRY_RSC = `
23
+ import {
24
+ renderStreaming,
25
+ createRequestHandler,
26
+ } from '@#metaName/runtime/ssr/server';
27
+ import { RSCServerSlot } from '@#metaName/runtime/rsc/client';
28
+ export { handleAction } from '@#metaName/runtime/rsc/server';
29
+
30
+ const handleRequest = async (request, ServerRoot, options) => {
31
+
32
+ const body = await renderStreaming(request,
33
+ <ServerRoot>
34
+ <RSCServerSlot />
35
+ </ServerRoot>,
36
+ {
37
+ ...options,
38
+ rscRoot: <options.RSCRoot />,
39
+ },
40
+ );
41
+
42
+ return new Response(body, {
43
+ headers: {
44
+ 'content-type': 'text/html; charset=utf-8',
45
+ #headers
46
+ },
47
+ })
48
+ };
49
+
50
+ export const requestHandler = createRequestHandler(handleRequest, {
51
+ enableRsc: true,
52
+ });
53
+ `;
22
54
  const serverIndex = (options) => {
23
55
  const { metaName = "modern-js", entryName } = options;
24
56
  return `
@@ -26,11 +58,39 @@ const serverIndex = (options) => {
26
58
  ${genHandlerCode(options)}
27
59
  `;
28
60
  };
29
- function genHandlerCode({ mode, metaName, customServerEntry, srcDirectory, internalSrcAlias }) {
61
+ const entryForCSRWithRSC = ({ metaName }) => {
62
+ return `
63
+ import App from './AppProxy';
64
+ import { renderRsc } from '@${metaName}/runtime/rsc/server'
65
+ export { handleAction } from '@${metaName}/runtime/rsc/server';
66
+
67
+
68
+ export const rscRequestHandler = ({
69
+ clientManifest
70
+ }) => {
71
+ const stream = renderRsc({
72
+ element: <App/>,
73
+ clientManifest,
74
+ })
75
+
76
+ const response = new Response(stream, {
77
+ headers: {
78
+ 'Transfer-Encoding': 'chunked',
79
+ },
80
+ });
81
+ return response
82
+ }
83
+ `;
84
+ };
85
+ function genHandlerCode({ mode, metaName, customServerEntry, srcDirectory, internalSrcAlias, enableRsc }) {
30
86
  if (customServerEntry) {
31
- return `export { default as requestHandler } from '${formatImportPath(customServerEntry.replace(srcDirectory, internalSrcAlias))}'`;
87
+ const realEntryPath = formatImportPath(customServerEntry.replace(srcDirectory, internalSrcAlias));
88
+ return `
89
+ export * from '${realEntryPath}';
90
+ export { default as requestHandler } from '${realEntryPath}'`;
32
91
  } else {
33
- const serverEntry = transformServerEntry(SERVER_ENTRY, {
92
+ const entrySource = enableRsc ? SERVER_ENTRY_RSC : SERVER_ENTRY;
93
+ const serverEntry = transformServerEntry(entrySource, {
34
94
  metaName: metaName || "modern-js",
35
95
  mode
36
96
  });
@@ -43,5 +103,6 @@ function transformServerEntry(source, options) {
43
103
  return output;
44
104
  }
45
105
  export {
106
+ entryForCSRWithRSC,
46
107
  serverIndex
47
108
  };
@@ -6,6 +6,10 @@ function setGlobalContext(context) {
6
6
  globalContext.appInit = context.appInit;
7
7
  globalContext.appConfig = typeof context.appConfig === "function" ? context.appConfig() : context.appConfig;
8
8
  globalContext.layoutApp = context.layoutApp;
9
+ globalContext.RSCRoot = context.RSCRoot;
10
+ }
11
+ function getGlobalRSCRoot() {
12
+ return globalContext.RSCRoot;
9
13
  }
10
14
  function setGlobalInternalRuntimeContext(context) {
11
15
  globalContext.internalRuntimeContext = context;
@@ -37,6 +41,7 @@ export {
37
41
  getGlobalAppInit,
38
42
  getGlobalInternalRuntimeContext,
39
43
  getGlobalLayoutApp,
44
+ getGlobalRSCRoot,
40
45
  getGlobalRoutes,
41
46
  getInitialContext,
42
47
  setGlobalContext,
@@ -1,9 +1,10 @@
1
1
  import { getPathname, parseCookie, parseHeaders, parseQuery } from "@modern-js/runtime-utils/universal/request";
2
- import { getGlobalAppInit, getGlobalInternalRuntimeContext } from "../context";
2
+ import { getGlobalAppInit, getGlobalInternalRuntimeContext, getGlobalRSCRoot } from "../context";
3
3
  import { getInitialContext } from "../context/runtime";
4
4
  import { createLoaderManager } from "../loader/loaderManager";
5
5
  import { createRoot } from "../react";
6
6
  import { CHUNK_CSS_PLACEHOLDER } from "./constants";
7
+ import { SSRErrors } from "./tracer";
7
8
  import { getSSRConfigByEntry, getSSRMode } from "./utils";
8
9
  function createSSRContext(request, options) {
9
10
  const { config, loaderContext, onError, onTiming, locals, resource, params, responseProxy, logger, metrics, reporter } = options;
@@ -61,9 +62,9 @@ function createSSRContext(request, options) {
61
62
  loaderFailureMode
62
63
  };
63
64
  }
64
- const createRequestHandler = async (handleRequest) => {
65
+ const createRequestHandler = async (handleRequest, createRequestOptions) => {
65
66
  const requestHandler = async (request, options) => {
66
- var _context_routerContext, _context_routerContext1;
67
+ var _context_routerContext, _context_routerContext1, _context_routerContext2;
67
68
  const Root = createRoot();
68
69
  const internalRuntimeContext = getGlobalInternalRuntimeContext();
69
70
  const hooks = internalRuntimeContext.hooks;
@@ -113,8 +114,12 @@ const createRequestHandler = async (handleRequest) => {
113
114
  };
114
115
  const initialData = await runBeforeRender(context);
115
116
  if (((_context_routerContext = context.routerContext) === null || _context_routerContext === void 0 ? void 0 : _context_routerContext.statusCode) && ((_context_routerContext1 = context.routerContext) === null || _context_routerContext1 === void 0 ? void 0 : _context_routerContext1.statusCode) !== 200) {
116
- var _context_routerContext2, _context_ssrContext;
117
- (_context_ssrContext = context.ssrContext) === null || _context_ssrContext === void 0 ? void 0 : _context_ssrContext.response.status((_context_routerContext2 = context.routerContext) === null || _context_routerContext2 === void 0 ? void 0 : _context_routerContext2.statusCode);
117
+ var _context_routerContext3, _context_ssrContext;
118
+ (_context_ssrContext = context.ssrContext) === null || _context_ssrContext === void 0 ? void 0 : _context_ssrContext.response.status((_context_routerContext3 = context.routerContext) === null || _context_routerContext3 === void 0 ? void 0 : _context_routerContext3.statusCode);
119
+ }
120
+ const errors = Object.values(((_context_routerContext2 = context.routerContext) === null || _context_routerContext2 === void 0 ? void 0 : _context_routerContext2.errors) || {});
121
+ if (errors.length > 0) {
122
+ options.onError(errors[0], SSRErrors.LOADER_ERROR);
118
123
  }
119
124
  context.initialData = initialData;
120
125
  const redirectResponse = getRedirectResponse(initialData);
@@ -125,7 +130,8 @@ const createRequestHandler = async (handleRequest) => {
125
130
  options.resource.htmlTemplate = htmlTemplate.replace("</head>", `${CHUNK_CSS_PLACEHOLDER}</head>`);
126
131
  const response = await handleRequest(request, Root, {
127
132
  ...options,
128
- runtimeContext: context
133
+ runtimeContext: context,
134
+ RSCRoot: (createRequestOptions === null || createRequestOptions === void 0 ? void 0 : createRequestOptions.enableRsc) && getGlobalRSCRoot()
129
135
  });
130
136
  Object.entries(responseProxy.headers).forEach(([key, value]) => {
131
137
  response.headers.set(key, value);
@@ -19,6 +19,8 @@ function buildShellAfterTemplate(afterAppTemplate, options) {
19
19
  async function injectJs(template, entryName2, nonce) {
20
20
  const { routeManifest } = runtimeContext;
21
21
  const { routeAssets } = routeManifest;
22
+ if (!routeAssets)
23
+ return template;
22
24
  const asyncEntry = routeAssets[`async-${entryName2}`];
23
25
  if (asyncEntry) {
24
26
  var _assets_filter;
@@ -1,5 +1,5 @@
1
+ import { renderSSRStream } from "@modern-js/render/ssr";
1
2
  import checkIsBot from "isbot";
2
- import { renderToReadableStream } from "react-dom/server";
3
3
  import { ESCAPED_SHELL_STREAM_END_MARK } from "../../../common";
4
4
  import { RenderLevel } from "../../constants";
5
5
  import { ShellChunkStatus, encodeForWebStream, getReadableStreamFromString } from "./shared";
@@ -7,7 +7,7 @@ import { getTemplates } from "./template";
7
7
  const createReadableStreamFromElement = async (request, rootElement, options) => {
8
8
  let shellChunkStatus = ShellChunkStatus.START;
9
9
  const chunkVec = [];
10
- const { htmlTemplate, runtimeContext, config, ssrConfig, entryName } = options;
10
+ const { htmlTemplate, runtimeContext, config, ssrConfig, entryName, rscRoot } = options;
11
11
  const { shellBefore, shellAfter } = await getTemplates(htmlTemplate, {
12
12
  renderLevel: RenderLevel.SERVER_RENDER,
13
13
  runtimeContext,
@@ -18,8 +18,12 @@ const createReadableStreamFromElement = async (request, rootElement, options) =>
18
18
  });
19
19
  try {
20
20
  var _options_onShellReady;
21
- const readableOriginal = await renderToReadableStream(rootElement, {
21
+ const readableOriginal = await renderSSRStream(rootElement, {
22
+ request,
23
+ clientManifest: options.rscClientManifest,
24
+ ssrManifest: options.rscSSRManifest,
22
25
  nonce: config.nonce,
26
+ rscRoot,
23
27
  onError(error) {
24
28
  var _options_onError;
25
29
  (_options_onError = options.onError) === null || _options_onError === void 0 ? void 0 : _options_onError.call(options, error);
@@ -47,7 +51,7 @@ const createReadableStreamFromElement = async (request, rootElement, options) =>
47
51
  const chunk = new TextDecoder().decode(value);
48
52
  chunkVec.push(chunk);
49
53
  let concatedChunk = chunkVec.join("");
50
- if (concatedChunk.endsWith(ESCAPED_SHELL_STREAM_END_MARK)) {
54
+ if (concatedChunk.includes(ESCAPED_SHELL_STREAM_END_MARK)) {
51
55
  concatedChunk = concatedChunk.replace(ESCAPED_SHELL_STREAM_END_MARK, "");
52
56
  shellChunkStatus = ShellChunkStatus.FINISH;
53
57
  controller.enqueue(encodeForWebStream(`${shellBefore}${concatedChunk}${shellAfter}`));
@@ -1,5 +1,5 @@
1
- import { createReadableStreamFromElement } from "./createReadableStream";
2
1
  import { createRenderStreaming } from "./shared";
2
+ const createReadableStreamFromElement = process.env.MODERN_SSR_ENV === "edge" ? import("./createReadableStream.worker").then((m) => m.createReadableStreamFromElement) : import("./createReadableStream").then((m) => m.createReadableStreamFromElement);
3
3
  const renderStreaming = createRenderStreaming(createReadableStreamFromElement);
4
4
  export {
5
5
  renderStreaming
@@ -1,8 +1,9 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
1
2
  import { run } from "@modern-js/runtime-utils/node";
2
3
  import { time } from "@modern-js/runtime-utils/time";
3
4
  import { parseHeaders } from "@modern-js/runtime-utils/universal/request";
4
5
  import { wrapRuntimeContextProvider } from "../../react/wrapper";
5
- import { SSRErrors, SSRTimings, createOnError, createOnTiming } from "../tracer";
6
+ import { SSRErrors, SSRTimings } from "../tracer";
6
7
  import { getSSRConfigByEntry } from "../utils";
7
8
  var ShellChunkStatus;
8
9
  (function(ShellChunkStatus2) {
@@ -28,25 +29,37 @@ function getReadableStreamFromString(content) {
28
29
  });
29
30
  return readableStream;
30
31
  }
31
- function createRenderStreaming(createReadableStreamFromElement) {
32
+ function createRenderStreaming(createReadableStreamPromise) {
32
33
  return async (request, serverRoot, options) => {
34
+ const createReadableStreamFromElement = await createReadableStreamPromise;
33
35
  const headersData = parseHeaders(request);
34
36
  return run(headersData, async () => {
35
37
  const end = time();
36
38
  const { runtimeContext, config, resource } = options;
37
- const onError = createOnError(options.onError);
38
- const onTiming = createOnTiming(options.onTiming);
39
+ const { onError, onTiming } = options;
39
40
  const { htmlTemplate, entryName } = resource;
40
41
  const ssrConfig = getSSRConfigByEntry(entryName, config.ssr, config.ssrByEntries);
41
- const rootElement = wrapRuntimeContextProvider(serverRoot, Object.assign(runtimeContext, {
42
+ const RSCServerRoot = ({ children }) => {
43
+ return /* @__PURE__ */ _jsx(_Fragment, {
44
+ children
45
+ });
46
+ };
47
+ let rootElement = wrapRuntimeContextProvider(serverRoot, Object.assign(runtimeContext, {
42
48
  ssr: true
43
49
  }));
50
+ rootElement = /* @__PURE__ */ _jsx(RSCServerRoot, {
51
+ children: rootElement
52
+ });
44
53
  const stream = await createReadableStreamFromElement(request, rootElement, {
45
54
  config,
46
55
  htmlTemplate,
47
56
  runtimeContext,
48
57
  ssrConfig,
49
58
  entryName,
59
+ rscClientManifest: options.rscClientManifest,
60
+ rscSSRManifest: options.rscSSRManifest,
61
+ rscServerManifest: options.rscServerManifest,
62
+ rscRoot: options.rscRoot,
50
63
  onShellReady() {
51
64
  const cost = end();
52
65
  onTiming(SSRTimings.RENDER_SHELL, cost);
@@ -56,10 +69,10 @@ function createRenderStreaming(createReadableStreamFromElement) {
56
69
  onTiming(SSRTimings.RENDER_HTML, cost);
57
70
  },
58
71
  onShellError(error) {
59
- onError(SSRErrors.RENDER_SHELL, error);
72
+ onError(error, SSRErrors.RENDER_SHELL);
60
73
  },
61
74
  onError(error) {
62
- onError(SSRErrors.RENDER_STREAM, error);
75
+ onError(error, SSRErrors.RENDER_STREAM);
63
76
  }
64
77
  });
65
78
  return stream;
@@ -8,7 +8,7 @@ import { wrapRuntimeContextProvider } from "../../react/wrapper";
8
8
  import { CHUNK_CSS_PLACEHOLDER, CHUNK_JS_PLACEHOLDER, HTML_PLACEHOLDER, SSR_DATA_PLACEHOLDER } from "../constants";
9
9
  import { createReplaceHelemt } from "../helmet";
10
10
  import { buildHtml } from "../shared";
11
- import { SSRErrors, SSRTimings, createOnError, createOnTiming } from "../tracer";
11
+ import { SSRErrors, SSRTimings } from "../tracer";
12
12
  import { getSSRConfigByEntry, safeReplace } from "../utils";
13
13
  import { LoadableCollector } from "./loadable";
14
14
  import { prefetch } from "./prefetch";
@@ -20,8 +20,8 @@ const renderString = async (request, serverRoot, options) => {
20
20
  var _runtimeContext_ssrContext;
21
21
  const { resource, runtimeContext, config, onError, onTiming } = options;
22
22
  const tracer = {
23
- onError: createOnError(onError),
24
- onTiming: createOnTiming(onTiming)
23
+ onError,
24
+ onTiming
25
25
  };
26
26
  const routerContext = runtimeContext.routerContext;
27
27
  const { htmlTemplate, entryName, loadableStats, routeManifest } = resource;
@@ -38,7 +38,7 @@ const renderString = async (request, serverRoot, options) => {
38
38
  chunkSet.renderLevel = RenderLevel.SERVER_PREFETCH;
39
39
  } catch (e) {
40
40
  chunkSet.renderLevel = RenderLevel.CLIENT_RENDER;
41
- tracer.onError(SSRErrors.PRERENDER, e);
41
+ tracer.onError(e, SSRErrors.PRERENDER);
42
42
  }
43
43
  const collectors = [
44
44
  new StyledCollector(chunkSet),
@@ -87,7 +87,7 @@ async function generateHtml(App, htmlTemplate, chunkSet, collectors, htmlModifie
87
87
  onTiming(SSRTimings.RENDER_HTML, cost);
88
88
  } catch (e) {
89
89
  chunkSet.renderLevel = RenderLevel.CLIENT_RENDER;
90
- onError(SSRErrors.RENDER_HTML, e);
90
+ onError(e, SSRErrors.RENDER_HTML);
91
91
  }
92
92
  await Promise.all(collectors.map((component) => component.effect()));
93
93
  const { ssrScripts, cssChunk, jsChunk } = chunkSet;
@@ -33,7 +33,7 @@ const prefetch = async (App, request, options, ssrConfig, { onError, onTiming })
33
33
  onTiming(SSRTimings.PRERENDER, cost);
34
34
  } catch (e) {
35
35
  const error = e;
36
- onError(SSRErrors.PRERENDER, error);
36
+ onError(error, SSRErrors.PRERENDER);
37
37
  throw e;
38
38
  }
39
39
  }
@@ -50,13 +50,13 @@ const prefetch = async (App, request, options, ssrConfig, { onError, onTiming })
50
50
  const cost = end();
51
51
  onTiming(SSRTimings.USE_LOADER, cost);
52
52
  } catch (e) {
53
- onError(SSRErrors.USE_LOADER, e);
53
+ onError(e, SSRErrors.USE_LOADER);
54
54
  throw e;
55
55
  }
56
56
  Object.keys(loadersData).forEach((id) => {
57
57
  const data = loadersData[id];
58
58
  if (data._error) {
59
- onError(SSRErrors.USE_LOADER, data._error);
59
+ onError(data._error, SSRErrors.USE_LOADER);
60
60
  delete data._error;
61
61
  }
62
62
  });
@@ -12,22 +12,9 @@ var SSRErrors;
12
12
  SSRErrors2["RENDER_HTML"] = "App Render To HTML";
13
13
  SSRErrors2["RENDER_STREAM"] = "An error occurs during streaming SSR";
14
14
  SSRErrors2["RENDER_SHELL"] = "An error occurs during streaming render shell";
15
+ SSRErrors2["LOADER_ERROR"] = "App error occurs during data loader";
15
16
  })(SSRErrors || (SSRErrors = {}));
16
- function createOnError(onError) {
17
- return (key, e) => {
18
- const error = e instanceof Error ? e : new Error("Unexpected Server Error");
19
- error.name = key;
20
- onError === null || onError === void 0 ? void 0 : onError(e);
21
- };
22
- }
23
- function createOnTiming(onTiming) {
24
- return (key, cost) => {
25
- onTiming === null || onTiming === void 0 ? void 0 : onTiming(key, cost);
26
- };
27
- }
28
17
  export {
29
18
  SSRErrors,
30
- SSRTimings,
31
- createOnError,
32
- createOnTiming
19
+ SSRTimings
33
20
  };
@@ -113,7 +113,7 @@ const generateCode = async (appContext, config, entrypoints, api) => {
113
113
  }
114
114
  };
115
115
  function generatorRegisterCode(internalDirectory, entryName, code) {
116
- fs.outputFileSync(path.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME}`), code, "utf8");
116
+ fs.outputFileSync(path.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME}.js`), code, "utf8");
117
117
  }
118
118
  export {
119
119
  generateCode,
@@ -110,6 +110,10 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
110
110
  }
111
111
  return "";
112
112
  };
113
+ const createLazyImport = ({ componentPath, routeId, webpackChunkName, eager }) => {
114
+ const importOptions = webpackChunkName ? `/* webpackChunkName: "${routeId}" */ ` : eager ? `/* webpackMode: "eager" */ ` : "";
115
+ return `() => import(${importOptions}'${componentPath}').then(routeModule => handleRouteModule(routeModule, "${routeId}")).catch(handleRouteModuleError)`;
116
+ };
113
117
  const traverseRouteTree = (route) => {
114
118
  let children;
115
119
  if ("children" in route && route.children) {
@@ -158,24 +162,32 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
158
162
  configsMap[config] = route.config;
159
163
  }
160
164
  if (route._component) {
161
- if (splitRouteChunks) {
162
- if (route.isRoot) {
163
- lazyImport = `() => import('${route._component}').then(routeModule => handleRouteModule(routeModule, "${route.id}")).catch(handleRouteModuleError) `;
164
- rootLayoutCode = `import RootLayout from '${route._component}'`;
165
- component = `RootLayout`;
166
- } else if (ssrMode === "string") {
167
- lazyImport = `() => import(/* webpackChunkName: "${route.id}" */ '${route._component}').then(routeModule => handleRouteModule(routeModule, "${route.id}")).catch(handleRouteModuleError) `;
168
- component = `loadable(${lazyImport})`;
165
+ if (route.isRoot) {
166
+ lazyImport = createLazyImport({
167
+ componentPath: route._component,
168
+ routeId: route.id
169
+ });
170
+ rootLayoutCode = `import RootLayout from '${route._component}'`;
171
+ component = "RootLayout";
172
+ } else if (splitRouteChunks) {
173
+ lazyImport = createLazyImport({
174
+ componentPath: route._component,
175
+ routeId: route.id,
176
+ webpackChunkName: true
177
+ });
178
+ component = ssrMode === "string" ? `loadable(${lazyImport})` : `lazy(${lazyImport})`;
179
+ } else {
180
+ if (ssrMode === "string") {
181
+ components.push(route._component);
182
+ component = `component_${components.length - 1}`;
169
183
  } else {
170
- lazyImport = `() => import(/* webpackChunkName: "${route.id}" */ '${route._component}').then(routeModule => handleRouteModule(routeModule, "${route.id}")).catch(handleRouteModuleError) `;
184
+ lazyImport = createLazyImport({
185
+ componentPath: route._component,
186
+ routeId: route.id,
187
+ eager: true
188
+ });
171
189
  component = `lazy(${lazyImport})`;
172
190
  }
173
- } else if (ssrMode === "string") {
174
- components.push(route._component);
175
- component = `component_${components.length - 1}`;
176
- } else {
177
- lazyImport = `() => import(/* webpackMode: "eager" */ '${route._component}').then(routeModule => handleRouteModule(routeModule, "${route.id}")).catch(handleRouteModuleError) `;
178
- component = `lazy(${lazyImport})`;
179
191
  }
180
192
  }
181
193
  } else if (route._component) {
@@ -0,0 +1 @@
1
+ export * from "@modern-js/render/client";
@@ -0,0 +1 @@
1
+ export * from "@modern-js/render/rsc";
@@ -5,5 +5,5 @@ export declare const INDEX_FILE_NAME = "index";
5
5
  export declare const ENTRY_BOOTSTRAP_FILE_NAME = "bootstrap.jsx";
6
6
  export declare const ENTRY_SERVER_BOOTSTRAP_FILE_NAME = "bootstrap.server.jsx";
7
7
  export declare const ENTRY_POINT_RUNTIME_REGISTER_FILE_NAME = "runtime-register.js";
8
- export declare const ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME = "runtime-global-context.js";
8
+ export declare const ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME = "runtime-global-context";
9
9
  export declare const ENTRY_POINT_REGISTER_FILE_NAME = "register.js";
@@ -1,5 +1,11 @@
1
1
  import type { RuntimePluginConfig } from '@modern-js/app-tools';
2
- export declare const index: ({ srcDirectory, internalSrcAlias, metaName, entry, entryName, customEntry, customBootstrap, mountId, }: {
2
+ export declare const entryForCSRWithRSC: ({ metaName, entryName, urlPath, mountId, }: {
3
+ metaName: string;
4
+ entryName: string;
5
+ urlPath?: string | undefined;
6
+ mountId?: string | undefined;
7
+ }) => string;
8
+ export declare const index: ({ srcDirectory, internalSrcAlias, metaName, entry, entryName, customEntry, customBootstrap, mountId, enableRsc, }: {
3
9
  srcDirectory: string;
4
10
  internalSrcAlias: string;
5
11
  metaName: string;
@@ -8,6 +14,7 @@ export declare const index: ({ srcDirectory, internalSrcAlias, metaName, entry,
8
14
  customEntry?: boolean | undefined;
9
15
  customBootstrap?: string | false | undefined;
10
16
  mountId?: string | undefined;
17
+ enableRsc?: boolean | undefined;
11
18
  }) => string;
12
19
  export declare const register: () => string;
13
20
  export declare const runtimeRegister: ({ entryName, srcDirectory, internalSrcAlias, metaName, runtimeConfigFile, runtimePlugins, }: {
@@ -25,3 +32,15 @@ export declare const runtimeGlobalContext: ({ srcDirectory, internalSrcAlias, me
25
32
  entry: string;
26
33
  customEntry?: boolean | undefined;
27
34
  }) => string;
35
+ export declare const runtimeGlobalContextForRSCServer: ({ metaName, }: {
36
+ metaName: string;
37
+ }) => string;
38
+ export declare const runtimeGlobalContextForRSCClient: ({ metaName, }: {
39
+ metaName: string;
40
+ }) => string;
41
+ export declare const AppProxyForRSC: ({ srcDirectory, internalSrcAlias, entry, customEntry, }: {
42
+ srcDirectory: string;
43
+ internalSrcAlias: string;
44
+ entry: string;
45
+ customEntry?: boolean | undefined;
46
+ }) => string;
@@ -2,11 +2,15 @@ type ServerIndexOptinos = GenHandlerCodeOptions & {
2
2
  entryName: string;
3
3
  };
4
4
  export declare const serverIndex: (options: ServerIndexOptinos) => string;
5
+ export declare const entryForCSRWithRSC: ({ metaName, }: {
6
+ metaName: string;
7
+ }) => string;
5
8
  type GenHandlerCodeOptions = {
6
9
  customServerEntry?: string | false;
7
10
  srcDirectory: string;
8
11
  internalSrcAlias: string;
9
12
  entry: string;
13
+ enableRsc?: boolean;
10
14
  } & TransformServerEntryOptions;
11
15
  type TransformServerEntryOptions = {
12
16
  metaName?: string;
@@ -26,10 +26,15 @@ interface GlobalContext {
26
26
  */
27
27
  layoutApp?: React.ComponentType;
28
28
  internalRuntimeContext?: InternalRuntimeContext<RuntimeExtends>;
29
+ /**
30
+ * RSCRoot
31
+ */
32
+ RSCRoot?: React.ComponentType;
29
33
  }
30
34
  export declare function setGlobalContext(context: Omit<GlobalContext, 'appConfig' | 'internalRuntimeContext'> & {
31
35
  appConfig?: () => AppConfig;
32
36
  }): void;
37
+ export declare function getGlobalRSCRoot(): import("react").ComponentType<{}> | undefined;
33
38
  export declare function setGlobalInternalRuntimeContext(context: InternalRuntimeContext<RuntimeExtends>): void;
34
39
  export declare function getGlobalInternalRuntimeContext(): InternalRuntimeContext<Required<import("@modern-js/plugin-v2").RuntimePluginExtends<import("../plugin/types").RuntimeConfig, import("./runtime").RuntimeContext, {}, {}>>>;
35
40
  export declare function getGlobalApp(): import("react").ComponentType<{}> | undefined;
@@ -7,5 +7,7 @@ export type HandleRequestOptions = Exclude<RequestHandlerOptions, 'staticGenerat
7
7
  };
8
8
  export type HandleRequest = (request: Request, ServerRoot: React.ComponentType, // App, routes,
9
9
  options: HandleRequestOptions) => Promise<Response>;
10
- export type CreateRequestHandler = (handleRequest: HandleRequest) => Promise<RequestHandler>;
10
+ export type CreateRequestHandler = (handleRequest: HandleRequest, options?: {
11
+ enableRsc: boolean;
12
+ }) => Promise<RequestHandler>;
11
13
  export declare const createRequestHandler: CreateRequestHandler;