From a8303837e2f33c8a82642b302ac57cf367af1bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=B8=85?= Date: Sat, 4 Nov 2023 08:40:07 -0500 Subject: [PATCH] fix(ssr): support ant design pro ssr (#11702) --- examples/ant-design-pro/config/config.ts | 25 +++-------- .../bundler-webpack/src/config/ssrPlugin.ts | 11 +++-- .../src/features/exportStatic/exportStatic.ts | 5 ++- packages/server/src/ssr.ts | 41 ++++++++++++------- 4 files changed, 44 insertions(+), 38 deletions(-) diff --git a/examples/ant-design-pro/config/config.ts b/examples/ant-design-pro/config/config.ts index 9537b4cf3432..82972dc7bb4b 100644 --- a/examples/ant-design-pro/config/config.ts +++ b/examples/ant-design-pro/config/config.ts @@ -313,28 +313,15 @@ export default defineConfig({ mfsu: { // esbuild: true, }, - chainWebpack(memo: any) { + chainWebpack(memo) { memo.plugin('monaco-editor').use(MonacoEditorWebpackPlugin, []); return memo; }, - // openAPI: [ - // { - // requestLibPath: "import { request } from 'umi'", - // // 或者使用在线的版本 - // // schemaPath: "https://gw.alipayobjects.com/os/antfincdn/M%24jrzTTYJN/oneapi.json" - // schemaPath: join(__dirname, 'oneapi.json'), - // mock: false, - // }, - // { - // requestLibPath: "import { request } from 'umi'", - // schemaPath: 'https://gw.alipayobjects.com/os/antfincdn/CA1dOm%2631B/openapi.json', - // projectName: 'swagger', - // }, - // ], - // nodeModulesTransform: { - // type: 'none', - // }, - // exportStatic: {}, + ssr: { + builder: 'webpack', + platform: 'node', + }, + exportStatic: {}, codeSplitting: { jsStrategy: 'granularChunks', }, diff --git a/packages/bundler-webpack/src/config/ssrPlugin.ts b/packages/bundler-webpack/src/config/ssrPlugin.ts index 0c2b5c473316..21b987744eb5 100644 --- a/packages/bundler-webpack/src/config/ssrPlugin.ts +++ b/packages/bundler-webpack/src/config/ssrPlugin.ts @@ -1,6 +1,6 @@ import type { - Compiler, Compilation, + Compiler, } from '@umijs/bundler-webpack/compiled/webpack'; import { sources } from '@umijs/bundler-webpack/compiled/webpack'; import { fsExtra } from '@umijs/utils'; @@ -23,9 +23,11 @@ const PLUGIN_NAME = 'SSR_PLUGIN'; class SSRPlugin { opts: IOpts; manifest: Map; + isGenManifest: boolean; constructor(opts: IOpts) { this.opts = opts; this.manifest = new Map(); + this.isGenManifest = false; } apply(compiler: Compiler) { // ref: https://github.com/webdeveric/webpack-assets-manifest @@ -70,13 +72,16 @@ class SSRPlugin { 2, ); if ( - process.env.NODE_ENV === 'production' || - this.opts.userConfig.writeToDisk + (process.env.NODE_ENV === 'production' || + this.opts.userConfig.writeToDisk) && + !this.isGenManifest ) { + // 如果已经生成了,就不管了。不然会报错重复添加 compilation.emitAsset( 'build-manifest.json', new sources.RawSource(assetsSource, false), ); + this.isGenManifest = true; } else { const outputPath = compiler.options.output.path!; fsExtra.mkdirpSync(outputPath); diff --git a/packages/preset-umi/src/features/exportStatic/exportStatic.ts b/packages/preset-umi/src/features/exportStatic/exportStatic.ts index 411a2b44e35d..864d3df9dbc4 100644 --- a/packages/preset-umi/src/features/exportStatic/exportStatic.ts +++ b/packages/preset-umi/src/features/exportStatic/exportStatic.ts @@ -31,10 +31,11 @@ function getExportHtmlData(routes: Record): IExportHtmlItem[] { if ( // skip layout !route.isLayout && + route?.path && // skip dynamic route for win, because `:` is not allowed in file name - (!IS_WIN || !route.path.includes('/:')) && + (!IS_WIN || !route?.path?.includes('/:')) && // skip `*` route, because `*` is not working for most site serve services - (!route.path.includes('*') || + (!route?.path?.includes('*') || // except `404.html` is404) ) { diff --git a/packages/server/src/ssr.ts b/packages/server/src/ssr.ts index e2312aae899f..56398612bdcd 100644 --- a/packages/server/src/ssr.ts +++ b/packages/server/src/ssr.ts @@ -95,14 +95,20 @@ function createJSXGenerator(opts: CreateRequestHandlerOptions) { .map( (id: string) => new Promise(async (resolve) => { - loaderData[id] = await executeLoader(id, routesWithServerLoader, serverLoaderArgs); + loaderData[id] = await executeLoader( + id, + routesWithServerLoader, + serverLoaderArgs, + ); resolve(); }), ), ); const manifest = - typeof opts.manifest === 'function' ? opts.manifest(sourceDir) : opts.manifest; + typeof opts.manifest === 'function' + ? opts.manifest(sourceDir) + : opts.manifest; const context = { routes, routeComponents, @@ -167,11 +173,11 @@ export function createMarkupGenerator(opts: CreateRequestHandlerOptions) { html = html.replace( /(<\/head>)/, [ - opts.helmetContext.helmet.title.toString(), - opts.helmetContext.helmet.priority.toString(), - opts.helmetContext.helmet.meta.toString(), - opts.helmetContext.helmet.link.toString(), - opts.helmetContext.helmet.script.toString(), + opts.helmetContext.helmet?.title?.toString(), + opts.helmetContext.helmet?.priority?.toString(), + opts.helmetContext.helmet?.meta?.toString(), + opts.helmetContext.helmet?.link?.toString(), + opts.helmetContext.helmet?.script?.toString(), '$1', ] .filter(Boolean) @@ -217,9 +223,12 @@ export default function createRequestHandler( return; } - const request = new Request(req.protocol + '://' + req.get('host') + req.originalUrl, { - headers: req.headers, - }); + const request = new Request( + req.protocol + '://' + req.get('host') + req.originalUrl, + { + headers: req.headers, + }, + ); const jsx = await jsxGeneratorDeferrer(req.url, { request }); if (!jsx) return next(); @@ -255,10 +264,12 @@ export function createUmiHandler(opts: CreateRequestHandlerOptions) { ...opts, ...params, }); - const jsx = await jsxGeneratorDeferrer(new URL(req.url).pathname, { request: req }); + const jsx = await jsxGeneratorDeferrer(new URL(req.url).pathname, { + request: req, + }); if (!jsx) { - throw new Error('no page resource') + throw new Error('no page resource'); } return ReactDomServer.renderToNodeStream(jsx.element); @@ -269,7 +280,9 @@ export function createUmiServerLoader(opts: CreateRequestHandlerOptions) { return async function (req: Request) { const query = Object.fromEntries(new URL(req.url).searchParams); // 切换路由场景下,会通过此 API 执行 server loader - return await executeLoader(query.route, opts.routesWithServerLoader, { request: req }); + return await executeLoader(query.route, opts.routesWithServerLoader, { + request: req, + }); }; } @@ -311,7 +324,7 @@ function createClientRoute(route: any) { async function executeLoader( routeKey: string, routesWithServerLoader: RouteLoaders, - serverLoaderArgs?: IServerLoaderArgs + serverLoaderArgs?: IServerLoaderArgs, ) { const mod = await routesWithServerLoader[routeKey](); if (!mod.serverLoader || typeof mod.serverLoader !== 'function') {