From 42c196602b58c940257502909bf034528f9f5561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A5=87=E9=A3=8E?= Date: Mon, 25 Sep 2023 21:43:33 +0800 Subject: [PATCH 1/6] =?UTF-8?q?feature:=20=E6=96=B0=E5=A2=9E=E7=94=A8?= =?UTF-8?q?=E4=BA=8ECDN=E8=BE=B9=E7=BC=98=E8=AE=A1=E7=AE=97=E4=BA=91?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=9A=84SSR=E8=AF=B7=E6=B1=82handle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/preset-umi/templates/server.tpl | 4 +- packages/server/src/ssr.ts | 53 +++++++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/packages/preset-umi/templates/server.tpl b/packages/preset-umi/templates/server.tpl index ca38d51c5cfe..2aab31563feb 100644 --- a/packages/preset-umi/templates/server.tpl +++ b/packages/preset-umi/templates/server.tpl @@ -4,7 +4,7 @@ import { createHistory as createClientHistory } from './core/history'; import { getPlugins as getClientPlugins } from './core/plugin'; import { ServerInsertedHTMLContext } from './core/serverInsertedHTMLContext'; import { PluginManager } from '{{{ umiPluginPath }}}'; -import createRequestHandler, { createMarkupGenerator } from '{{{ umiServerPath }}}'; +import createRequestHandler, { createMarkupGenerator, createUnioHandler, createUnioSeaverLoader } from '{{{ umiServerPath }}}'; let helmetContext; @@ -54,6 +54,8 @@ const createOpts = { ServerInsertedHTMLContext, }; const requestHandler = createRequestHandler(createOpts); +const unioHandler = createUnioHandler(createOpts); +const unioSeaverLoader = createUnioSeaverLoader(createOpts); export const _markupGenerator = createMarkupGenerator(createOpts); diff --git a/packages/server/src/ssr.ts b/packages/server/src/ssr.ts index 515e965dbf9d..dda937f6233a 100644 --- a/packages/server/src/ssr.ts +++ b/packages/server/src/ssr.ts @@ -1,7 +1,7 @@ import React, { ReactElement } from 'react'; import * as ReactDomServer from 'react-dom/server'; import { matchRoutes } from 'react-router-dom'; -import { Writable } from 'stream'; +import { Writable, Readable } from 'stream'; import type { IRoutesById } from './types'; interface RouteLoaders { @@ -235,6 +235,57 @@ export default function createRequestHandler( }; } +export function createUnioHandler( + opts: CreateRequestHandlerOptions, +) { + const jsxGeneratorDeferrer = createJSXGenerator(opts); + + return async function (req: any) { + const jsx = await jsxGeneratorDeferrer(req.url); + + if (!jsx) { + throw Error('jsx is null'); + } + + const readable = new Readable(); + const writable = new Writable(); + + writable._write = (chunk, _encoding, next) => { + readable.push(chunk); + next(); + }; + + writable.on('finish', async () => { + readable.push(await getGenerateStaticHTML()); + readable.push(null); // 关闭流 + }); + + const stream = await ReactDomServer.renderToPipeableStream(jsx.element, { + bootstrapScripts: [jsx.manifest.assets['umi.js'] || '/umi.js'], + onShellReady() { + stream.pipe(writable); + }, + onError(x: any) { + console.error(x); + }, + }); + return readable; + }; +} + +export function createUnioSeaverLoader( + opts: CreateRequestHandlerOptions, +) { + return async function (req: any) { + // 切换路由场景下,会通过此 API 执行 server loader + const data = await executeLoader( + req.query.route, + opts.routesWithServerLoader, + ); + return Readable.from(JSON.stringify(data), {encoding: 'utf8'}) + }; +} + function matchRoutesForSSR(reqUrl: string, routesById: IRoutesById) { return ( matchRoutes(createClientRoutes({ routesById }), reqUrl)?.map( From 6b37a596b824d7ae1b8f64946ee0a29e925baeb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A5=87=E9=A3=8E?= Date: Mon, 25 Sep 2023 21:47:48 +0800 Subject: [PATCH 2/6] =?UTF-8?q?feature:=20=E6=96=B0=E5=A2=9E=E7=94=A8?= =?UTF-8?q?=E4=BA=8ECDN=E8=BE=B9=E7=BC=98=E8=AE=A1=E7=AE=97=E4=BA=91?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=9A=84SSR=E8=AF=B7=E6=B1=82handle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/server/src/ssr.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/server/src/ssr.ts b/packages/server/src/ssr.ts index dda937f6233a..1120bfcec372 100644 --- a/packages/server/src/ssr.ts +++ b/packages/server/src/ssr.ts @@ -277,9 +277,10 @@ export function createUnioSeaverLoader( opts: CreateRequestHandlerOptions, ) { return async function (req: any) { + const query = Object.fromEntries(new URL(req.url).searchParams) // 切换路由场景下,会通过此 API 执行 server loader const data = await executeLoader( - req.query.route, + query.route, opts.routesWithServerLoader, ); return Readable.from(JSON.stringify(data), {encoding: 'utf8'}) From 59aff8430d2d02f6d6fe6305cc7d24010df9ec5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A5=87=E9=A3=8E?= Date: Tue, 26 Sep 2023 10:31:56 +0800 Subject: [PATCH 3/6] =?UTF-8?q?feature:=20=E6=96=B0=E5=A2=9E=E7=94=A8?= =?UTF-8?q?=E4=BA=8ECDN=E8=BE=B9=E7=BC=98=E8=AE=A1=E7=AE=97=E4=BA=91?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=9A=84SSR=E8=AF=B7=E6=B1=82handle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/preset-umi/templates/server.tpl | 6 +-- packages/server/src/ssr.ts | 62 ++++++++++++------------ 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/packages/preset-umi/templates/server.tpl b/packages/preset-umi/templates/server.tpl index 2aab31563feb..3ae0fd1c2699 100644 --- a/packages/preset-umi/templates/server.tpl +++ b/packages/preset-umi/templates/server.tpl @@ -4,7 +4,7 @@ import { createHistory as createClientHistory } from './core/history'; import { getPlugins as getClientPlugins } from './core/plugin'; import { ServerInsertedHTMLContext } from './core/serverInsertedHTMLContext'; import { PluginManager } from '{{{ umiPluginPath }}}'; -import createRequestHandler, { createMarkupGenerator, createUnioHandler, createUnioSeaverLoader } from '{{{ umiServerPath }}}'; +import createRequestHandler, { createMarkupGenerator, createUmiHandler, createUmiServerLoader } from '{{{ umiServerPath }}}'; let helmetContext; @@ -54,8 +54,8 @@ const createOpts = { ServerInsertedHTMLContext, }; const requestHandler = createRequestHandler(createOpts); -const unioHandler = createUnioHandler(createOpts); -const unioSeaverLoader = createUnioSeaverLoader(createOpts); +export const renderRoot = createUmiHandler(createOpts); +export const serverLoader = createUmiServerLoader(createOpts); export const _markupGenerator = createMarkupGenerator(createOpts); diff --git a/packages/server/src/ssr.ts b/packages/server/src/ssr.ts index 1120bfcec372..dbc041e87cc6 100644 --- a/packages/server/src/ssr.ts +++ b/packages/server/src/ssr.ts @@ -235,55 +235,57 @@ export default function createRequestHandler( }; } -export function createUnioHandler( +export function createUmiHandler( opts: CreateRequestHandlerOptions, ) { const jsxGeneratorDeferrer = createJSXGenerator(opts); - return async function (req: any) { - const jsx = await jsxGeneratorDeferrer(req.url); + return function (req: Request) { + return new Promise(async (resolve, reject) => { + const jsx = await jsxGeneratorDeferrer(req.url); - if (!jsx) { - throw Error('jsx is null'); - } + if (!jsx) { + reject(new Error('jsx is null')); + return; + } - const readable = new Readable(); - const writable = new Writable(); + const readable = new Readable(); + const writable = new Writable(); - writable._write = (chunk, _encoding, next) => { - readable.push(chunk); - next(); - }; + writable._write = (chunk, _encoding, next) => { + readable.push(chunk); + next(); + }; - writable.on('finish', async () => { - readable.push(await getGenerateStaticHTML()); - readable.push(null); // 关闭流 - }); + writable.on('finish', async () => { + readable.push(await getGenerateStaticHTML()); + readable.push(null); // 关闭流 + }); - const stream = await ReactDomServer.renderToPipeableStream(jsx.element, { - bootstrapScripts: [jsx.manifest.assets['umi.js'] || '/umi.js'], - onShellReady() { - stream.pipe(writable); - }, - onError(x: any) { - console.error(x); - }, - }); - return readable; + const stream = await ReactDomServer.renderToPipeableStream(jsx.element, { + bootstrapScripts: [jsx.manifest.assets['umi.js'] || '/umi.js'], + onShellReady() { + stream.pipe(writable); + }, + onError(err: any) { + reject(err); + }, + }); + resolve(readable); + }) }; } -export function createUnioSeaverLoader( +export function createUmiServerLoader( opts: CreateRequestHandlerOptions, ) { - return async function (req: any) { + return async function (req: Request) { const query = Object.fromEntries(new URL(req.url).searchParams) // 切换路由场景下,会通过此 API 执行 server loader - const data = await executeLoader( + return await executeLoader( query.route, opts.routesWithServerLoader, ); - return Readable.from(JSON.stringify(data), {encoding: 'utf8'}) }; } From d4c7dc323aa47115aacb98a8e45de20d91e40aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A5=87=E9=A3=8E?= Date: Tue, 26 Sep 2023 15:19:26 +0800 Subject: [PATCH 4/6] =?UTF-8?q?feature:=20=E6=96=B0=E5=A2=9E=E7=94=A8?= =?UTF-8?q?=E4=BA=8ECDN=E8=BE=B9=E7=BC=98=E8=AE=A1=E7=AE=97=E4=BA=91?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=9A=84SSR=E8=AF=B7=E6=B1=82handle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/server/src/ssr.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/server/src/ssr.ts b/packages/server/src/ssr.ts index dbc041e87cc6..909480c9f871 100644 --- a/packages/server/src/ssr.ts +++ b/packages/server/src/ssr.ts @@ -242,24 +242,23 @@ export function createUmiHandler( return function (req: Request) { return new Promise(async (resolve, reject) => { - const jsx = await jsxGeneratorDeferrer(req.url); + const jsx = await jsxGeneratorDeferrer(new URL(req.url).pathname); if (!jsx) { reject(new Error('jsx is null')); return; } - const readable = new Readable(); + let buf = Buffer.alloc(0) const writable = new Writable(); writable._write = (chunk, _encoding, next) => { - readable.push(chunk); + buf = Buffer.concat([buf, chunk]); next(); }; writable.on('finish', async () => { - readable.push(await getGenerateStaticHTML()); - readable.push(null); // 关闭流 + resolve(Readable.from(buf)) }); const stream = await ReactDomServer.renderToPipeableStream(jsx.element, { @@ -271,7 +270,6 @@ export function createUmiHandler( reject(err); }, }); - resolve(readable); }) }; } From 5f8a5445c53400d8abc8c0836273eba97e6c495c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A5=87=E9=A3=8E?= Date: Tue, 26 Sep 2023 15:51:53 +0800 Subject: [PATCH 5/6] =?UTF-8?q?feature:=20=E6=96=B0=E5=A2=9E=E7=94=A8?= =?UTF-8?q?=E4=BA=8ECDN=E8=BE=B9=E7=BC=98=E8=AE=A1=E7=AE=97=E4=BA=91?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=9A=84SSR=E8=AF=B7=E6=B1=82handle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/server/src/ssr.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/ssr.ts b/packages/server/src/ssr.ts index 909480c9f871..9dde45b617fa 100644 --- a/packages/server/src/ssr.ts +++ b/packages/server/src/ssr.ts @@ -245,7 +245,7 @@ export function createUmiHandler( const jsx = await jsxGeneratorDeferrer(new URL(req.url).pathname); if (!jsx) { - reject(new Error('jsx is null')); + reject(new Error('找不到资源')); return; } From de4aae8c60592067aeb7ba20e9ee7bcd5588978b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A5=87=E9=A3=8E?= Date: Tue, 26 Sep 2023 15:57:49 +0800 Subject: [PATCH 6/6] =?UTF-8?q?feature:=20=E6=96=B0=E5=A2=9E=E7=94=A8?= =?UTF-8?q?=E4=BA=8ECDN=E8=BE=B9=E7=BC=98=E8=AE=A1=E7=AE=97=E4=BA=91?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=9A=84SSR=E8=AF=B7=E6=B1=82handle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/server/src/ssr.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/ssr.ts b/packages/server/src/ssr.ts index 9dde45b617fa..13d62f7b4b94 100644 --- a/packages/server/src/ssr.ts +++ b/packages/server/src/ssr.ts @@ -245,7 +245,7 @@ export function createUmiHandler( const jsx = await jsxGeneratorDeferrer(new URL(req.url).pathname); if (!jsx) { - reject(new Error('找不到资源')); + reject(new Error('no page resource')); return; }