From d34c1bc8ef4fb390cbb0fd7b7469e19fe28c2962 Mon Sep 17 00:00:00 2001 From: fz6m <59400654+fz6m@users.noreply.github.com> Date: Wed, 5 Jul 2023 00:50:57 +0800 Subject: [PATCH] feat: add transition router feature --- docs/docs/api/config.md | 9 +++ .../transitionRouter/transitionRouter.ts | 55 +++++++++++++++++++ packages/preset-umi/src/index.ts | 1 + 3 files changed, 65 insertions(+) create mode 100644 packages/preset-umi/src/features/transitionRouter/transitionRouter.ts diff --git a/docs/docs/api/config.md b/docs/docs/api/config.md index 10a7d2c1c7fc..d522def4c36e 100644 --- a/docs/docs/api/config.md +++ b/docs/docs/api/config.md @@ -1442,6 +1442,15 @@ theme: { '@primary-color': '#1DA57A' } 配置全局页面 title,暂时只支持静态的 Title。 +## transitionRouter + +- 类型:`object` +- 默认值:`null` + +仅 React 18 可用。 + +在切换页面时自动使用 `startTransition` 标记为非紧急更新,这可以避免 loading 态突然出现又消失的闪烁效果等[问题](https://react.dev/reference/react/Suspense#preventing-already-revealed-content-from-hiding),提升用户体验。 + ## verifyCommit - 类型:`{ scope: string[]; allowEmoji: boolean }` diff --git a/packages/preset-umi/src/features/transitionRouter/transitionRouter.ts b/packages/preset-umi/src/features/transitionRouter/transitionRouter.ts new file mode 100644 index 000000000000..c7a2d70b4c9a --- /dev/null +++ b/packages/preset-umi/src/features/transitionRouter/transitionRouter.ts @@ -0,0 +1,55 @@ +import { winPath } from '@umijs/utils'; +import { join } from 'path'; +import type { IApi } from '../../types'; + +export default (api: IApi) => { + api.describe({ + config: { + schema({ zod }) { + return zod.object({}); + }, + }, + enableBy: api.EnableBy.config, + }); + + api.onGenerateFiles(() => { + if (api.userConfig.mpa || api.config.mpa) { + throw new Error('transitionRouter plugin does not support mpa mode'); + } + if (api.appData.framework !== 'react') { + throw new Error('transitionRouter plugin only support react framework'); + } + const isReact18 = ( + api.appData.react?.version as string | undefined + )?.startsWith('18'); + if (!isReact18) { + throw new Error('transitionRouter plugin only support react@18'); + } + + // https://github.com/remix-run/remix/issues/5763 + api.writeTmpFile({ + path: 'runtime.ts', + content: ` +import { startTransition } from 'react'; + +export const modifyClientRenderOpts = (context) => { + const h = context.history + const originPush = h.push + const originReplace = h.replace + h.push = (...args) => { + startTransition(() => originPush.apply(h, args)) + } + h.replace = (...args) => { + startTransition(() => originReplace.apply(h, args)) + } + return context +} +`, + }); + }); + + const pluginDir = `plugin-${api.plugin.key}`; + api.addRuntimePlugin(() => [ + winPath(join(api.paths.absTmpPath, `${pluginDir}/runtime.ts`)), + ]); +}; diff --git a/packages/preset-umi/src/index.ts b/packages/preset-umi/src/index.ts index 01e759cf4514..94edd60e5327 100644 --- a/packages/preset-umi/src/index.ts +++ b/packages/preset-umi/src/index.ts @@ -57,6 +57,7 @@ export default () => { require.resolve('./features/swc/swc'), require.resolve('./features/ui/ui'), require.resolve('./features/hmrGuardian/hmrGuardian'), + require.resolve('./features/transitionRouter/transitionRouter'), // commands require.resolve('./commands/build'),