@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.
- package/dist/cjs/cli/code.js +67 -28
- package/dist/cjs/cli/constants.js +1 -1
- package/dist/cjs/cli/ssr/index.js +4 -1
- package/dist/cjs/cli/template.js +91 -4
- package/dist/cjs/cli/template.server.js +65 -3
- package/dist/cjs/core/context/index.js +6 -0
- package/dist/cjs/core/server/requestHandler.js +11 -5
- package/dist/cjs/core/server/stream/afterTemplate.js +2 -0
- package/dist/cjs/core/server/stream/createReadableStream.worker.js +8 -4
- package/dist/cjs/core/server/stream/index.js +12 -2
- package/dist/cjs/core/server/stream/shared.js +19 -6
- package/dist/cjs/core/server/string/index.js +4 -4
- package/dist/cjs/core/server/string/prefetch.js +3 -3
- package/dist/cjs/core/server/tracer.js +3 -18
- package/dist/cjs/router/cli/code/index.js +1 -1
- package/dist/cjs/router/cli/code/templates.js +27 -15
- package/dist/cjs/rsc/client.js +22 -0
- package/dist/cjs/rsc/server.js +22 -0
- package/dist/esm/cli/code.js +178 -51
- package/dist/esm/cli/constants.js +1 -1
- package/dist/esm/cli/ssr/index.js +4 -1
- package/dist/esm/cli/template.js +29 -4
- package/dist/esm/cli/template.server.js +11 -3
- package/dist/esm/core/context/index.js +5 -0
- package/dist/esm/core/server/requestHandler.js +12 -6
- package/dist/esm/core/server/stream/afterTemplate.js +5 -0
- package/dist/esm/core/server/stream/createReadableStream.worker.js +9 -5
- package/dist/esm/core/server/stream/index.js +5 -1
- package/dist/esm/core/server/stream/shared.js +76 -54
- package/dist/esm/core/server/string/index.js +5 -5
- package/dist/esm/core/server/string/prefetch.js +3 -3
- package/dist/esm/core/server/tracer.js +2 -16
- package/dist/esm/router/cli/code/index.js +1 -1
- package/dist/esm/router/cli/code/templates.js +29 -16
- package/dist/esm/rsc/client.js +1 -0
- package/dist/esm/rsc/server.js +1 -0
- package/dist/esm-node/cli/code.js +67 -28
- package/dist/esm-node/cli/constants.js +1 -1
- package/dist/esm-node/cli/ssr/index.js +4 -1
- package/dist/esm-node/cli/template.js +87 -4
- package/dist/esm-node/cli/template.server.js +64 -3
- package/dist/esm-node/core/context/index.js +5 -0
- package/dist/esm-node/core/server/requestHandler.js +12 -6
- package/dist/esm-node/core/server/stream/afterTemplate.js +2 -0
- package/dist/esm-node/core/server/stream/createReadableStream.worker.js +8 -4
- package/dist/esm-node/core/server/stream/index.js +1 -1
- package/dist/esm-node/core/server/stream/shared.js +20 -7
- package/dist/esm-node/core/server/string/index.js +5 -5
- package/dist/esm-node/core/server/string/prefetch.js +3 -3
- package/dist/esm-node/core/server/tracer.js +2 -15
- package/dist/esm-node/router/cli/code/index.js +1 -1
- package/dist/esm-node/router/cli/code/templates.js +27 -15
- package/dist/esm-node/rsc/client.js +1 -0
- package/dist/esm-node/rsc/server.js +1 -0
- package/dist/types/cli/constants.d.ts +1 -1
- package/dist/types/cli/template.d.ts +20 -1
- package/dist/types/cli/template.server.d.ts +4 -0
- package/dist/types/core/context/index.d.ts +5 -0
- package/dist/types/core/server/requestHandler.d.ts +3 -1
- package/dist/types/core/server/stream/shared.d.ts +8 -2
- package/dist/types/core/server/tracer.d.ts +3 -5
- package/dist/types/core/types.d.ts +3 -2
- package/dist/types/rsc/client.d.ts +1 -0
- package/dist/types/rsc/server.d.ts +1 -0
- 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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
117
|
-
(_context_ssrContext = context.ssrContext) === null || _context_ssrContext === void 0 ? void 0 : _context_ssrContext.response.status((
|
|
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
|
|
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.
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
|
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
|
|
72
|
+
onError(error, SSRErrors.RENDER_SHELL);
|
|
60
73
|
},
|
|
61
74
|
onError(error) {
|
|
62
|
-
onError(SSRErrors.RENDER_STREAM
|
|
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
|
|
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
|
|
24
|
-
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
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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 (
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
10
|
+
export type CreateRequestHandler = (handleRequest: HandleRequest, options?: {
|
|
11
|
+
enableRsc: boolean;
|
|
12
|
+
}) => Promise<RequestHandler>;
|
|
11
13
|
export declare const createRequestHandler: CreateRequestHandler;
|