diff --git a/packages/preset-umi/src/features/ssr/ssr.ts b/packages/preset-umi/src/features/ssr/ssr.ts
index 128a9de01944..d72a04857c18 100644
--- a/packages/preset-umi/src/features/ssr/ssr.ts
+++ b/packages/preset-umi/src/features/ssr/ssr.ts
@@ -25,6 +25,7 @@ export default (api: IApi) => {
return zod
.object({
serverBuildPath: zod.string(),
+ serverBuildMode: zod.enum(['express', 'worker']),
platform: zod.string(),
builder: zod.enum(['esbuild', 'webpack']),
renderFromRoot: zod.boolean(),
@@ -49,6 +50,22 @@ export default (api: IApi) => {
logger.warn(`SSR feature is in beta, may be unstable`);
});
+ api.modifyConfig((memo) => {
+ // define SSR_BUILD_MODE to strip useless logic
+ memo.define ??= {};
+ memo.define.SSR_BUILD_MODE = api.config.ssr.serverBuildMode || 'express';
+
+ if (api.config.serverBuildMode === 'worker') {
+ // use browser version of react-dom/server for worker mode
+ // ref: https://github.com/facebook/react/blob/f86afca090b668d8be10b642750844759768d1ad/packages/react-server-dom-webpack/package.json#L52
+ memo.alias['react-dom/server$'] = winPath(
+ join(memo.alias['react-dom'], 'server.browser.js'),
+ );
+ }
+
+ return memo;
+ });
+
api.addMiddlewares(() => [
async (req, res, next) => {
const modulePath = absServerBuildPath(api);
diff --git a/packages/server/src/ssr.ts b/packages/server/src/ssr.ts
index fb26a6eaa92d..17ac843337e2 100644
--- a/packages/server/src/ssr.ts
+++ b/packages/server/src/ssr.ts
@@ -288,10 +288,17 @@ export default function createRequestHandler(
const replaceServerHTMLScript = ``;
- if (typeof FetchEvent !== 'undefined' && args[0] instanceof FetchEvent) {
+ if (process.env.SSR_BUILD_MODE === 'worker') {
// worker mode
const [ev, workerOpts] = args as IWorkerRequestHandlerArgs;
const { pathname, searchParams } = new URL(ev.request.url);
+ let asyncRespondWith: (
+ v: Parameters[0],
+ ) => void;
+
+ // respondWith must be called synchronously
+ // ref: https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/respondWith
+ ev.respondWith(new Promise((r) => (asyncRespondWith = r)));
ret = {
req: {
@@ -316,7 +323,7 @@ export default function createRequestHandler(
res = await workerOpts.modifyResponse(res);
}
- ev.respondWith(res);
+ asyncRespondWith(res);
},
async sendPage(jsx) {
const [JSXProvider, serverInsertedHTMLCallbacks] = createJSXProvider(
@@ -360,7 +367,7 @@ export default function createRequestHandler(
res = await workerOpts.modifyResponse(res);
}
- ev.respondWith(res);
+ asyncRespondWith(res);
},
otherwise() {
throw new Error('no page resource');