From 0c2fc109ac409b3c9be46eca08af44259eb0ac44 Mon Sep 17 00:00:00 2001 From: PeachScript Date: Sun, 7 Apr 2024 15:50:40 +0800 Subject: [PATCH 1/4] fix: wrong react-dom server api for worker ssr mode --- packages/preset-umi/src/features/ssr/ssr.ts | 17 +++++++++++++++++ packages/server/src/ssr.ts | 13 ++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) 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'); From 7a5640176e6309c82958780b91151c322a71d400 Mon Sep 17 00:00:00 2001 From: PeachScript Date: Sun, 7 Apr 2024 15:58:43 +0800 Subject: [PATCH 2/4] refactor: rename config --- packages/preset-umi/src/features/ssr/ssr.ts | 9 +++++---- packages/server/src/ssr.ts | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/preset-umi/src/features/ssr/ssr.ts b/packages/preset-umi/src/features/ssr/ssr.ts index d72a04857c18..83f4a0ecb993 100644 --- a/packages/preset-umi/src/features/ssr/ssr.ts +++ b/packages/preset-umi/src/features/ssr/ssr.ts @@ -25,7 +25,7 @@ export default (api: IApi) => { return zod .object({ serverBuildPath: zod.string(), - serverBuildMode: zod.enum(['express', 'worker']), + serverBuildTarget: zod.enum(['express', 'worker']), platform: zod.string(), builder: zod.enum(['esbuild', 'webpack']), renderFromRoot: zod.boolean(), @@ -51,11 +51,12 @@ export default (api: IApi) => { }); api.modifyConfig((memo) => { - // define SSR_BUILD_MODE to strip useless logic + // define SSR_BUILD_TARGET to strip useless logic memo.define ??= {}; - memo.define.SSR_BUILD_MODE = api.config.ssr.serverBuildMode || 'express'; + memo.define.SSR_BUILD_TARGET = + api.config.ssr.serverBuildTarget || 'express'; - if (api.config.serverBuildMode === 'worker') { + if (api.config.serverBuildTarget === '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( diff --git a/packages/server/src/ssr.ts b/packages/server/src/ssr.ts index 17ac843337e2..2fe9652be93d 100644 --- a/packages/server/src/ssr.ts +++ b/packages/server/src/ssr.ts @@ -288,7 +288,7 @@ export default function createRequestHandler( const replaceServerHTMLScript = ``; - if (process.env.SSR_BUILD_MODE === 'worker') { + if (process.env.SSR_BUILD_TARGET === 'worker') { // worker mode const [ev, workerOpts] = args as IWorkerRequestHandlerArgs; const { pathname, searchParams } = new URL(ev.request.url); From 5d2cbbc3a3e2d706461e4a6f903f4d48102e14d4 Mon Sep 17 00:00:00 2001 From: PeachScript Date: Sun, 7 Apr 2024 16:06:29 +0800 Subject: [PATCH 3/4] refactor: correct logic --- packages/preset-umi/src/features/ssr/ssr.ts | 28 +++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/packages/preset-umi/src/features/ssr/ssr.ts b/packages/preset-umi/src/features/ssr/ssr.ts index 83f4a0ecb993..59def10b65a9 100644 --- a/packages/preset-umi/src/features/ssr/ssr.ts +++ b/packages/preset-umi/src/features/ssr/ssr.ts @@ -17,6 +17,7 @@ export default (api: IApi) => { const webpackBuilder: typeof import('./webpack/webpack') = importLazy( require.resolve('./webpack/webpack'), ); + let serverBuildTarget: string; api.describe({ key: 'ssr', @@ -50,23 +51,36 @@ export default (api: IApi) => { logger.warn(`SSR feature is in beta, may be unstable`); }); - api.modifyConfig((memo) => { - // define SSR_BUILD_TARGET to strip useless logic - memo.define ??= {}; - memo.define.SSR_BUILD_TARGET = - api.config.ssr.serverBuildTarget || 'express'; + api.modifyDefaultConfig((memo) => { + if (serverBuildTarget === 'worker') { + const oReactDom = memo.alias['react-dom']; + + // put react-dom after react-dom/server + delete memo.alias['react-dom']; - if (api.config.serverBuildTarget === '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'), + join( + api.service.configDefaults.alias['react-dom'], + 'server.browser.js', + ), ); + memo.alias['react-dom'] = oReactDom; } return memo; }); + api.modifyConfig((memo) => { + // define SSR_BUILD_TARGET to strip useless logic + memo.define ??= {}; + serverBuildTarget = memo.define['process.env.SSR_BUILD_TARGET'] = + memo.ssr.serverBuildTarget || 'express'; + + return memo; + }); + api.addMiddlewares(() => [ async (req, res, next) => { const modulePath = absServerBuildPath(api); From f657c31432fdcea446fc5b22e5a38d93598b7d5c Mon Sep 17 00:00:00 2001 From: PeachScript Date: Sun, 7 Apr 2024 16:56:02 +0800 Subject: [PATCH 4/4] fix: locked stream in ssr --- packages/server/src/ssr.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/server/src/ssr.ts b/packages/server/src/ssr.ts index 2fe9652be93d..f65a0bc86dfe 100644 --- a/packages/server/src/ssr.ts +++ b/packages/server/src/ssr.ts @@ -353,9 +353,7 @@ export default function createRequestHandler( }, }); - stream.pipeThrough(transformStream); - - let res = new Response(stream, { + let res = new Response(stream.pipeThrough(transformStream), { headers: { 'content-type': 'text/html; charset=utf-8', },