Skip to content

Commit

Permalink
fix: wrong react-dom server api for worker ssr mode (#12263)
Browse files Browse the repository at this point in the history
* fix: wrong react-dom server api for worker ssr mode

* refactor: rename config

* refactor: correct logic

* fix: locked stream in ssr
  • Loading branch information
PeachScript authored Apr 11, 2024
1 parent a7dd292 commit 7ccf522
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 6 deletions.
32 changes: 32 additions & 0 deletions packages/preset-umi/src/features/ssr/ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -25,6 +26,7 @@ export default (api: IApi) => {
return zod
.object({
serverBuildPath: zod.string(),
serverBuildTarget: zod.enum(['express', 'worker']),
platform: zod.string(),
builder: zod.enum(['esbuild', 'webpack']),
renderFromRoot: zod.boolean(),
Expand All @@ -49,6 +51,36 @@ export default (api: IApi) => {
logger.warn(`SSR feature is in beta, may be unstable`);
});

api.modifyDefaultConfig((memo) => {
if (serverBuildTarget === 'worker') {
const oReactDom = memo.alias['react-dom'];

// put react-dom after react-dom/server
delete memo.alias['react-dom'];

// 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(
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);
Expand Down
17 changes: 11 additions & 6 deletions packages/server/src/ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,10 +288,17 @@ export default function createRequestHandler(

const replaceServerHTMLScript = `<script>!function(){var e=document.getElementById("${SERVER_INSERTED_HTML}");e&&(Array.from(e.children).forEach(e=>{document.head.appendChild(e)}),e.remove())}();</script>`;

if (typeof FetchEvent !== 'undefined' && args[0] instanceof FetchEvent) {
if (process.env.SSR_BUILD_TARGET === 'worker') {
// worker mode
const [ev, workerOpts] = args as IWorkerRequestHandlerArgs;
const { pathname, searchParams } = new URL(ev.request.url);
let asyncRespondWith: (
v: Parameters<FetchEvent['respondWith']>[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: {
Expand All @@ -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(
Expand Down Expand Up @@ -346,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',
},
Expand All @@ -360,7 +365,7 @@ export default function createRequestHandler(
res = await workerOpts.modifyResponse(res);
}

ev.respondWith(res);
asyncRespondWith(res);
},
otherwise() {
throw new Error('no page resource');
Expand Down

0 comments on commit 7ccf522

Please sign in to comment.