@modern-js/runtime 2.64.0 → 2.64.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 (69) 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/browser/index.js +10 -2
  7. package/dist/cjs/core/context/index.js +6 -0
  8. package/dist/cjs/core/server/requestHandler.js +11 -5
  9. package/dist/cjs/core/server/stream/afterTemplate.js +2 -0
  10. package/dist/cjs/core/server/stream/createReadableStream.worker.js +8 -4
  11. package/dist/cjs/core/server/stream/index.js +12 -2
  12. package/dist/cjs/core/server/stream/shared.js +19 -6
  13. package/dist/cjs/core/server/string/index.js +4 -4
  14. package/dist/cjs/core/server/string/prefetch.js +3 -3
  15. package/dist/cjs/core/server/tracer.js +3 -18
  16. package/dist/cjs/router/cli/code/index.js +1 -1
  17. package/dist/cjs/rsc/client.js +22 -0
  18. package/dist/cjs/rsc/server.js +22 -0
  19. package/dist/cjs/state/cli/index.js +2 -2
  20. package/dist/esm/cli/code.js +178 -51
  21. package/dist/esm/cli/constants.js +1 -1
  22. package/dist/esm/cli/ssr/index.js +4 -1
  23. package/dist/esm/cli/template.js +29 -4
  24. package/dist/esm/cli/template.server.js +11 -3
  25. package/dist/esm/core/browser/index.js +5 -1
  26. package/dist/esm/core/context/index.js +5 -0
  27. package/dist/esm/core/server/requestHandler.js +12 -6
  28. package/dist/esm/core/server/stream/afterTemplate.js +5 -0
  29. package/dist/esm/core/server/stream/createReadableStream.worker.js +9 -5
  30. package/dist/esm/core/server/stream/index.js +5 -1
  31. package/dist/esm/core/server/stream/shared.js +76 -54
  32. package/dist/esm/core/server/string/index.js +5 -5
  33. package/dist/esm/core/server/string/prefetch.js +3 -3
  34. package/dist/esm/core/server/tracer.js +2 -16
  35. package/dist/esm/router/cli/code/index.js +1 -1
  36. package/dist/esm/rsc/client.js +1 -0
  37. package/dist/esm/rsc/server.js +1 -0
  38. package/dist/esm/state/cli/index.js +2 -2
  39. package/dist/esm-node/cli/code.js +67 -28
  40. package/dist/esm-node/cli/constants.js +1 -1
  41. package/dist/esm-node/cli/ssr/index.js +4 -1
  42. package/dist/esm-node/cli/template.js +87 -4
  43. package/dist/esm-node/cli/template.server.js +64 -3
  44. package/dist/esm-node/core/browser/index.js +5 -1
  45. package/dist/esm-node/core/context/index.js +5 -0
  46. package/dist/esm-node/core/server/requestHandler.js +12 -6
  47. package/dist/esm-node/core/server/stream/afterTemplate.js +2 -0
  48. package/dist/esm-node/core/server/stream/createReadableStream.worker.js +8 -4
  49. package/dist/esm-node/core/server/stream/index.js +1 -1
  50. package/dist/esm-node/core/server/stream/shared.js +20 -7
  51. package/dist/esm-node/core/server/string/index.js +5 -5
  52. package/dist/esm-node/core/server/string/prefetch.js +3 -3
  53. package/dist/esm-node/core/server/tracer.js +2 -15
  54. package/dist/esm-node/router/cli/code/index.js +1 -1
  55. package/dist/esm-node/rsc/client.js +1 -0
  56. package/dist/esm-node/rsc/server.js +1 -0
  57. package/dist/esm-node/state/cli/index.js +2 -2
  58. package/dist/types/cli/constants.d.ts +1 -1
  59. package/dist/types/cli/template.d.ts +22 -3
  60. package/dist/types/cli/template.server.d.ts +4 -0
  61. package/dist/types/core/browser/index.d.ts +4 -0
  62. package/dist/types/core/context/index.d.ts +5 -0
  63. package/dist/types/core/server/requestHandler.d.ts +3 -1
  64. package/dist/types/core/server/stream/shared.d.ts +8 -2
  65. package/dist/types/core/server/tracer.d.ts +3 -5
  66. package/dist/types/core/types.d.ts +3 -2
  67. package/dist/types/rsc/client.d.ts +1 -0
  68. package/dist/types/rsc/server.d.ts +1 -0
  69. package/package.json +28 -11
@@ -31,6 +31,11 @@ function buildShellAfterTemplate(afterAppTemplate, options) {
31
31
  return _ts_generator(this, function(_state) {
32
32
  routeManifest = runtimeContext.routeManifest;
33
33
  routeAssets = routeManifest.routeAssets;
34
+ if (!routeAssets)
35
+ return [
36
+ 2,
37
+ template
38
+ ];
34
39
  asyncEntry = routeAssets["async-".concat(entryName2)];
35
40
  if (asyncEntry) {
36
41
  ;
@@ -1,20 +1,20 @@
1
1
  import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
2
2
  import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
3
+ import { renderSSRStream } from "@modern-js/render/ssr";
3
4
  import checkIsBot from "isbot";
4
- import { renderToReadableStream } from "react-dom/server";
5
5
  import { ESCAPED_SHELL_STREAM_END_MARK } from "../../../common";
6
6
  import { RenderLevel } from "../../constants";
7
7
  import { ShellChunkStatus, encodeForWebStream, getReadableStreamFromString } from "./shared";
8
8
  import { getTemplates } from "./template";
9
9
  var createReadableStreamFromElement = function() {
10
10
  var _ref = _async_to_generator(function(request, rootElement, options) {
11
- var shellChunkStatus, chunkVec, htmlTemplate, runtimeContext, config, ssrConfig, entryName, _ref2, shellBefore, shellAfter, _options_onShellReady, readableOriginal, isbot, reader, stream, e, fallbackHtml, stream1;
11
+ var shellChunkStatus, chunkVec, htmlTemplate, runtimeContext, config, ssrConfig, entryName, rscRoot, _ref2, shellBefore, shellAfter, _options_onShellReady, readableOriginal, isbot, reader, stream, e, fallbackHtml, stream1;
12
12
  return _ts_generator(this, function(_state) {
13
13
  switch (_state.label) {
14
14
  case 0:
15
15
  shellChunkStatus = ShellChunkStatus.START;
16
16
  chunkVec = [];
17
- htmlTemplate = options.htmlTemplate, runtimeContext = options.runtimeContext, config = options.config, ssrConfig = options.ssrConfig, entryName = options.entryName;
17
+ htmlTemplate = options.htmlTemplate, runtimeContext = options.runtimeContext, config = options.config, ssrConfig = options.ssrConfig, entryName = options.entryName, rscRoot = options.rscRoot;
18
18
  return [
19
19
  4,
20
20
  getTemplates(htmlTemplate, {
@@ -38,8 +38,12 @@ var createReadableStreamFromElement = function() {
38
38
  ]);
39
39
  return [
40
40
  4,
41
- renderToReadableStream(rootElement, {
41
+ renderSSRStream(rootElement, {
42
+ request,
43
+ clientManifest: options.rscClientManifest,
44
+ ssrManifest: options.rscSSRManifest,
42
45
  nonce: config.nonce,
46
+ rscRoot,
43
47
  onError: function onError(error) {
44
48
  var _options_onError;
45
49
  (_options_onError = options.onError) === null || _options_onError === void 0 ? void 0 : _options_onError.call(options, error);
@@ -95,7 +99,7 @@ var createReadableStreamFromElement = function() {
95
99
  chunk = new TextDecoder().decode(value);
96
100
  chunkVec.push(chunk);
97
101
  concatedChunk = chunkVec.join("");
98
- if (concatedChunk.endsWith(ESCAPED_SHELL_STREAM_END_MARK)) {
102
+ if (concatedChunk.includes(ESCAPED_SHELL_STREAM_END_MARK)) {
99
103
  concatedChunk = concatedChunk.replace(ESCAPED_SHELL_STREAM_END_MARK, "");
100
104
  shellChunkStatus = ShellChunkStatus.FINISH;
101
105
  controller.enqueue(encodeForWebStream("".concat(shellBefore).concat(concatedChunk).concat(shellAfter)));
@@ -1,5 +1,9 @@
1
- import { createReadableStreamFromElement } from "./createReadableStream";
2
1
  import { createRenderStreaming } from "./shared";
2
+ var createReadableStreamFromElement = process.env.MODERN_SSR_ENV === "edge" ? import("./createReadableStream.worker").then(function(m) {
3
+ return m.createReadableStreamFromElement;
4
+ }) : import("./createReadableStream").then(function(m) {
5
+ return m.createReadableStreamFromElement;
6
+ });
3
7
  var renderStreaming = createRenderStreaming(createReadableStreamFromElement);
4
8
  export {
5
9
  renderStreaming
@@ -1,10 +1,11 @@
1
1
  import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
2
2
  import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
3
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
3
4
  import { run } from "@modern-js/runtime-utils/node";
4
5
  import { time } from "@modern-js/runtime-utils/time";
5
6
  import { parseHeaders } from "@modern-js/runtime-utils/universal/request";
6
7
  import { wrapRuntimeContextProvider } from "../../react/wrapper";
7
- import { SSRErrors, SSRTimings, createOnError, createOnTiming } from "../tracer";
8
+ import { SSRErrors, SSRTimings } from "../tracer";
8
9
  import { getSSRConfigByEntry } from "../utils";
9
10
  var ShellChunkStatus;
10
11
  (function(ShellChunkStatus2) {
@@ -30,62 +31,83 @@ function getReadableStreamFromString(content) {
30
31
  });
31
32
  return readableStream;
32
33
  }
33
- function createRenderStreaming(createReadableStreamFromElement) {
34
+ function createRenderStreaming(createReadableStreamPromise) {
34
35
  return function() {
35
36
  var _ref = _async_to_generator(function(request, serverRoot, options) {
36
- var headersData;
37
+ var createReadableStreamFromElement, headersData;
37
38
  return _ts_generator(this, function(_state) {
38
- headersData = parseHeaders(request);
39
- return [
40
- 2,
41
- run(headersData, /* @__PURE__ */ _async_to_generator(function() {
42
- var end, runtimeContext, config, resource, onError, onTiming, htmlTemplate, entryName, ssrConfig, rootElement, stream;
43
- return _ts_generator(this, function(_state2) {
44
- switch (_state2.label) {
45
- case 0:
46
- end = time();
47
- runtimeContext = options.runtimeContext, config = options.config, resource = options.resource;
48
- onError = createOnError(options.onError);
49
- onTiming = createOnTiming(options.onTiming);
50
- htmlTemplate = resource.htmlTemplate, entryName = resource.entryName;
51
- ssrConfig = getSSRConfigByEntry(entryName, config.ssr, config.ssrByEntries);
52
- rootElement = wrapRuntimeContextProvider(serverRoot, Object.assign(runtimeContext, {
53
- ssr: true
54
- }));
55
- return [
56
- 4,
57
- createReadableStreamFromElement(request, rootElement, {
58
- config,
59
- htmlTemplate,
60
- runtimeContext,
61
- ssrConfig,
62
- entryName,
63
- onShellReady: function onShellReady() {
64
- var cost = end();
65
- onTiming(SSRTimings.RENDER_SHELL, cost);
66
- },
67
- onAllReady: function onAllReady() {
68
- var cost = end();
69
- onTiming(SSRTimings.RENDER_HTML, cost);
70
- },
71
- onShellError: function onShellError(error) {
72
- onError(SSRErrors.RENDER_SHELL, error);
73
- },
74
- onError: function onError1(error) {
75
- onError(SSRErrors.RENDER_STREAM, error);
76
- }
77
- })
78
- ];
79
- case 1:
80
- stream = _state2.sent();
81
- return [
82
- 2,
83
- stream
84
- ];
85
- }
86
- });
87
- }))
88
- ];
39
+ switch (_state.label) {
40
+ case 0:
41
+ return [
42
+ 4,
43
+ createReadableStreamPromise
44
+ ];
45
+ case 1:
46
+ createReadableStreamFromElement = _state.sent();
47
+ headersData = parseHeaders(request);
48
+ return [
49
+ 2,
50
+ run(headersData, /* @__PURE__ */ _async_to_generator(function() {
51
+ var end, runtimeContext, config, resource, onError, onTiming, htmlTemplate, entryName, ssrConfig, RSCServerRoot, rootElement, stream;
52
+ return _ts_generator(this, function(_state2) {
53
+ switch (_state2.label) {
54
+ case 0:
55
+ end = time();
56
+ runtimeContext = options.runtimeContext, config = options.config, resource = options.resource;
57
+ onError = options.onError, onTiming = options.onTiming;
58
+ htmlTemplate = resource.htmlTemplate, entryName = resource.entryName;
59
+ ssrConfig = getSSRConfigByEntry(entryName, config.ssr, config.ssrByEntries);
60
+ RSCServerRoot = function(param) {
61
+ var children = param.children;
62
+ return /* @__PURE__ */ _jsx(_Fragment, {
63
+ children
64
+ });
65
+ };
66
+ rootElement = wrapRuntimeContextProvider(serverRoot, Object.assign(runtimeContext, {
67
+ ssr: true
68
+ }));
69
+ rootElement = /* @__PURE__ */ _jsx(RSCServerRoot, {
70
+ children: rootElement
71
+ });
72
+ return [
73
+ 4,
74
+ createReadableStreamFromElement(request, rootElement, {
75
+ config,
76
+ htmlTemplate,
77
+ runtimeContext,
78
+ ssrConfig,
79
+ entryName,
80
+ rscClientManifest: options.rscClientManifest,
81
+ rscSSRManifest: options.rscSSRManifest,
82
+ rscServerManifest: options.rscServerManifest,
83
+ rscRoot: options.rscRoot,
84
+ onShellReady: function onShellReady() {
85
+ var cost = end();
86
+ onTiming(SSRTimings.RENDER_SHELL, cost);
87
+ },
88
+ onAllReady: function onAllReady() {
89
+ var cost = end();
90
+ onTiming(SSRTimings.RENDER_HTML, cost);
91
+ },
92
+ onShellError: function onShellError(error) {
93
+ onError(error, SSRErrors.RENDER_SHELL);
94
+ },
95
+ onError: function onError1(error) {
96
+ onError(error, SSRErrors.RENDER_STREAM);
97
+ }
98
+ })
99
+ ];
100
+ case 1:
101
+ stream = _state2.sent();
102
+ return [
103
+ 2,
104
+ stream
105
+ ];
106
+ }
107
+ });
108
+ }))
109
+ ];
110
+ }
89
111
  });
90
112
  });
91
113
  return function(request, serverRoot, options) {
@@ -11,7 +11,7 @@ import { wrapRuntimeContextProvider } from "../../react/wrapper";
11
11
  import { CHUNK_CSS_PLACEHOLDER, CHUNK_JS_PLACEHOLDER, HTML_PLACEHOLDER, SSR_DATA_PLACEHOLDER } from "../constants";
12
12
  import { createReplaceHelemt } from "../helmet";
13
13
  import { buildHtml } from "../shared";
14
- import { SSRErrors, SSRTimings, createOnError, createOnTiming } from "../tracer";
14
+ import { SSRErrors, SSRTimings } from "../tracer";
15
15
  import { getSSRConfigByEntry, safeReplace } from "../utils";
16
16
  import { LoadableCollector } from "./loadable";
17
17
  import { prefetch } from "./prefetch";
@@ -31,8 +31,8 @@ var renderString = function() {
31
31
  case 0:
32
32
  resource = options.resource, runtimeContext = options.runtimeContext, config = options.config, onError = options.onError, onTiming = options.onTiming;
33
33
  tracer = {
34
- onError: createOnError(onError),
35
- onTiming: createOnTiming(onTiming)
34
+ onError,
35
+ onTiming
36
36
  };
37
37
  routerContext = runtimeContext.routerContext;
38
38
  htmlTemplate = resource.htmlTemplate, entryName = resource.entryName, loadableStats = resource.loadableStats, routeManifest = resource.routeManifest;
@@ -66,7 +66,7 @@ var renderString = function() {
66
66
  case 3:
67
67
  e = _state2.sent();
68
68
  chunkSet.renderLevel = RenderLevel.CLIENT_RENDER;
69
- tracer.onError(SSRErrors.PRERENDER, e);
69
+ tracer.onError(e, SSRErrors.PRERENDER);
70
70
  return [
71
71
  3,
72
72
  4
@@ -143,7 +143,7 @@ function _generateHtml() {
143
143
  onTiming(SSRTimings.RENDER_HTML, cost);
144
144
  } catch (e) {
145
145
  chunkSet.renderLevel = RenderLevel.CLIENT_RENDER;
146
- onError(SSRErrors.RENDER_HTML, e);
146
+ onError(e, SSRErrors.RENDER_HTML);
147
147
  }
148
148
  return [
149
149
  4,
@@ -44,7 +44,7 @@ var prefetch = function() {
44
44
  onTiming(SSRTimings.PRERENDER, cost);
45
45
  } catch (e2) {
46
46
  error = e2;
47
- onError(SSRErrors.PRERENDER, error);
47
+ onError(error, SSRErrors.PRERENDER);
48
48
  throw e2;
49
49
  }
50
50
  }
@@ -81,13 +81,13 @@ var prefetch = function() {
81
81
  ];
82
82
  case 3:
83
83
  e = _state2.sent();
84
- onError(SSRErrors.USE_LOADER, e);
84
+ onError(e, SSRErrors.USE_LOADER);
85
85
  throw e;
86
86
  case 4:
87
87
  Object.keys(loadersData).forEach(function(id) {
88
88
  var data = loadersData[id];
89
89
  if (data._error) {
90
- onError(SSRErrors.USE_LOADER, data._error);
90
+ onError(data._error, SSRErrors.USE_LOADER);
91
91
  delete data._error;
92
92
  }
93
93
  });
@@ -1,4 +1,3 @@
1
- import { _ as _instanceof } from "@swc/helpers/_/_instanceof";
2
1
  var SSRTimings;
3
2
  (function(SSRTimings2) {
4
3
  SSRTimings2["PRERENDER"] = "ssr-prerender";
@@ -13,22 +12,9 @@ var SSRErrors;
13
12
  SSRErrors2["RENDER_HTML"] = "App Render To HTML";
14
13
  SSRErrors2["RENDER_STREAM"] = "An error occurs during streaming SSR";
15
14
  SSRErrors2["RENDER_SHELL"] = "An error occurs during streaming render shell";
15
+ SSRErrors2["LOADER_ERROR"] = "App error occurs during data loader";
16
16
  })(SSRErrors || (SSRErrors = {}));
17
- function createOnError(onError) {
18
- return function(key, e) {
19
- var error = _instanceof(e, Error) ? e : new Error("Unexpected Server Error");
20
- error.name = key;
21
- onError === null || onError === void 0 ? void 0 : onError(e);
22
- };
23
- }
24
- function createOnTiming(onTiming) {
25
- return function(key, cost) {
26
- onTiming === null || onTiming === void 0 ? void 0 : onTiming(key, cost);
27
- };
28
- }
29
17
  export {
30
18
  SSRErrors,
31
- SSRTimings,
32
- createOnError,
33
- createOnTiming
19
+ SSRTimings
34
20
  };
@@ -242,7 +242,7 @@ var generateCode = function() {
242
242
  };
243
243
  }();
244
244
  function generatorRegisterCode(internalDirectory, entryName, code) {
245
- fs.outputFileSync(path.resolve(internalDirectory, "./".concat(entryName, "/").concat(ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME)), code, "utf8");
245
+ fs.outputFileSync(path.resolve(internalDirectory, "./".concat(entryName, "/").concat(ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME, ".js")), code, "utf8");
246
246
  }
247
247
  export {
248
248
  generateCode,
@@ -0,0 +1 @@
1
+ export * from "@modern-js/render/client";
@@ -0,0 +1 @@
1
+ export * from "@modern-js/render/rsc";
@@ -11,8 +11,8 @@ var statePlugin = function() {
11
11
  var entrypoint = param.entrypoint, plugins = param.plugins;
12
12
  var _getEntryOptions;
13
13
  var entryName = entrypoint.entryName, isMainEntry = entrypoint.isMainEntry;
14
- var userConfig = api.useResolvedConfigContext();
15
- var _api_useAppContext = api.useAppContext(), packageName = _api_useAppContext.packageName, metaName = _api_useAppContext.metaName;
14
+ var userConfig = api.getNormalizedConfig();
15
+ var _api_getAppContext = api.getAppContext(), packageName = _api_getAppContext.packageName, metaName = _api_getAppContext.metaName;
16
16
  var stateConfig = (_getEntryOptions = getEntryOptions(entryName, isMainEntry, userConfig.runtime, userConfig.runtimeByEntries, packageName)) === null || _getEntryOptions === void 0 ? void 0 : _getEntryOptions.state;
17
17
  if (stateConfig) {
18
18
  plugins.push({
@@ -22,7 +22,7 @@ function getSSRMode(entry, config) {
22
22
  const generateCode = async (entrypoints, appContext, config, hooks) => {
23
23
  const { mountId } = config.html;
24
24
  const { enableAsyncEntry } = config.source;
25
- const { runtimeConfigFile, internalDirectory, internalSrcAlias, metaName, srcDirectory } = appContext;
25
+ const { runtimeConfigFile, internalDirectory, internalSrcAlias, metaName, srcDirectory, serverRoutes } = appContext;
26
26
  await Promise.all(entrypoints.map(async (entrypoint) => {
27
27
  const { entryName, isAutoMount, entry, customEntry, customBootstrap, customServerEntry } = entrypoint;
28
28
  const { plugins: runtimePlugins } = await hooks._internalRuntimePlugins.call({
@@ -30,25 +30,37 @@ const generateCode = async (entrypoints, appContext, config, hooks) => {
30
30
  plugins: []
31
31
  });
32
32
  if (isAutoMount) {
33
- const indexCode = template.index({
34
- srcDirectory,
35
- internalSrcAlias,
36
- metaName,
37
- entry,
38
- entryName,
39
- customEntry,
40
- customBootstrap,
41
- mountId
42
- });
43
- const indexFile = path.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_FILE_NAME}`);
44
- fs.outputFileSync(indexFile, indexCode, "utf8");
45
33
  const ssrMode = getSSRMode(entryName, config);
34
+ let indexCode = "";
35
+ if (!ssrMode && config.server.rsc) {
36
+ var _serverRoutes_find;
37
+ indexCode = template.entryForCSRWithRSC({
38
+ metaName,
39
+ entryName,
40
+ mountId,
41
+ urlPath: (_serverRoutes_find = serverRoutes.find((route) => route.entryName === entryName)) === null || _serverRoutes_find === void 0 ? void 0 : _serverRoutes_find.urlPath
42
+ });
43
+ } else {
44
+ indexCode = template.index({
45
+ srcDirectory,
46
+ internalSrcAlias,
47
+ metaName,
48
+ entry,
49
+ entryName,
50
+ customEntry,
51
+ customBootstrap,
52
+ mountId,
53
+ enableRsc: config.server.rsc
54
+ });
55
+ }
56
+ const indexFile = path.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_FILE_NAME}`);
57
+ await fs.outputFile(indexFile, indexCode, "utf8");
46
58
  if (enableAsyncEntry) {
47
59
  const bootstrapFile = path.resolve(internalDirectory, `./${entryName}/${ENTRY_BOOTSTRAP_FILE_NAME}`);
48
- fs.outputFileSync(bootstrapFile, `import(/* webpackChunkName: "async-${entryName}" */ './${INDEX_FILE_NAME}');`, "utf8");
60
+ await fs.outputFile(bootstrapFile, `import(/* webpackChunkName: "async-${entryName}" */ './${INDEX_FILE_NAME}');`, "utf8");
49
61
  const bootstrapServerFile = path.resolve(internalDirectory, `./${entryName}/${ENTRY_SERVER_BOOTSTRAP_FILE_NAME}`);
50
62
  if (ssrMode) {
51
- fs.outputFileSync(bootstrapServerFile, `export const requestHandler = import('./${SERVER_ENTRY_POINT_FILE_NAME}').then((m) => m.requestHandler)`, "utf8");
63
+ await fs.outputFile(bootstrapServerFile, `export const requestHandler = import('./${SERVER_ENTRY_POINT_FILE_NAME}').then((m) => m.requestHandler)`, "utf8");
52
64
  }
53
65
  }
54
66
  if (ssrMode) {
@@ -59,14 +71,21 @@ const generateCode = async (entrypoints, appContext, config, hooks) => {
59
71
  metaName,
60
72
  mode: ssrMode,
61
73
  customServerEntry,
62
- srcDirectory
74
+ srcDirectory,
75
+ enableRsc: config.server.rsc
63
76
  });
64
77
  const indexServerFile = path.resolve(internalDirectory, `./${entryName}/${SERVER_ENTRY_POINT_FILE_NAME}`);
65
- fs.outputFileSync(indexServerFile, indexServerCode, "utf8");
78
+ await fs.outputFile(indexServerFile, indexServerCode, "utf8");
79
+ } else if (config.server.rsc) {
80
+ const indexServerFile = path.resolve(internalDirectory, `./${entryName}/${SERVER_ENTRY_POINT_FILE_NAME}`);
81
+ const indexServerCode = serverTemplate.entryForCSRWithRSC({
82
+ metaName
83
+ });
84
+ await fs.outputFile(indexServerFile, indexServerCode, "utf8");
66
85
  }
67
86
  const registerCode = template.register();
68
87
  const registerFile = path.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_REGISTER_FILE_NAME}`);
69
- fs.outputFileSync(registerFile, registerCode, "utf8");
88
+ await fs.outputFile(registerFile, registerCode, "utf8");
70
89
  const registerRuntimeCode = template.runtimeRegister({
71
90
  entryName,
72
91
  srcDirectory,
@@ -76,16 +95,36 @@ const generateCode = async (entrypoints, appContext, config, hooks) => {
76
95
  runtimePlugins
77
96
  });
78
97
  const registerRuntimeFile = path.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_RUNTIME_REGISTER_FILE_NAME}`);
79
- fs.outputFileSync(registerRuntimeFile, registerRuntimeCode, "utf8");
80
- const contextCode = template.runtimeGlobalContext({
81
- srcDirectory,
82
- internalSrcAlias,
83
- metaName,
84
- entry,
85
- customEntry
86
- });
87
- const contextFile = path.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME}`);
88
- fs.outputFileSync(contextFile, contextCode, "utf8");
98
+ await fs.outputFile(registerRuntimeFile, registerRuntimeCode, "utf8");
99
+ let contextCode = "";
100
+ if (!config.server.rsc) {
101
+ contextCode = template.runtimeGlobalContext({
102
+ srcDirectory,
103
+ internalSrcAlias,
104
+ metaName,
105
+ entry,
106
+ customEntry
107
+ });
108
+ } else {
109
+ const AppProxyPath = path.join(internalDirectory, entryName, "./AppProxy.jsx");
110
+ const appProxyCode = template.AppProxyForRSC({
111
+ srcDirectory,
112
+ internalSrcAlias,
113
+ entry,
114
+ customEntry
115
+ });
116
+ await fs.outputFile(AppProxyPath, appProxyCode);
117
+ contextCode = template.runtimeGlobalContextForRSCClient({
118
+ metaName
119
+ });
120
+ const contextServerCode = template.runtimeGlobalContextForRSCServer({
121
+ metaName
122
+ });
123
+ const contextFile2 = path.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME}.server.js`);
124
+ await fs.outputFile(contextFile2, contextServerCode, "utf8");
125
+ }
126
+ const contextFile = path.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME}.js`);
127
+ await fs.outputFile(contextFile, contextCode, "utf8");
89
128
  }
90
129
  }));
91
130
  };
@@ -5,7 +5,7 @@ const INDEX_FILE_NAME = "index";
5
5
  const ENTRY_BOOTSTRAP_FILE_NAME = "bootstrap.jsx";
6
6
  const ENTRY_SERVER_BOOTSTRAP_FILE_NAME = "bootstrap.server.jsx";
7
7
  const ENTRY_POINT_RUNTIME_REGISTER_FILE_NAME = "runtime-register.js";
8
- const ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME = "runtime-global-context.js";
8
+ const ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME = "runtime-global-context";
9
9
  const ENTRY_POINT_REGISTER_FILE_NAME = "register.js";
10
10
  export {
11
11
  APP_FILE_NAME,
@@ -23,13 +23,16 @@ const ssrBuilderPlugin = (modernAPI) => ({
23
23
  name: "@modern-js/builder-plugin-ssr",
24
24
  setup(api) {
25
25
  api.modifyEnvironmentConfig((config, { name, mergeEnvironmentConfig }) => {
26
+ var _userConfig_deploy_worker, _userConfig_deploy, _userConfig_server;
26
27
  const isServerEnvironment = config.output.target === "node" || name === "workerSSR";
27
28
  const userConfig = modernAPI.getNormalizedConfig();
29
+ const ssrEnv = ((_userConfig_deploy = userConfig.deploy) === null || _userConfig_deploy === void 0 ? void 0 : (_userConfig_deploy_worker = _userConfig_deploy.worker) === null || _userConfig_deploy_worker === void 0 ? void 0 : _userConfig_deploy_worker.ssr) || ((_userConfig_server = userConfig.server) === null || _userConfig_server === void 0 ? void 0 : _userConfig_server.rsc) ? "edge" : "node";
28
30
  const useLoadablePlugin = isUseSSRBundle(userConfig) && !isServerEnvironment && checkUseStringSSR(userConfig);
29
31
  return mergeEnvironmentConfig(config, {
30
32
  source: {
31
33
  define: {
32
- "process.env.MODERN_TARGET": isServerEnvironment ? JSON.stringify("node") : JSON.stringify("browser")
34
+ "process.env.MODERN_TARGET": isServerEnvironment ? JSON.stringify("node") : JSON.stringify("browser"),
35
+ "process.env.MODERN_SSR_ENV": JSON.stringify(ssrEnv)
33
36
  }
34
37
  },
35
38
  tools: {
@@ -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
  };