diff --git a/docs/.dumi/components/Contributing/index.less b/docs/.dumi/components/Contributing/index.less index e777d1ef628b..814c5625efc0 100644 --- a/docs/.dumi/components/Contributing/index.less +++ b/docs/.dumi/components/Contributing/index.less @@ -13,5 +13,9 @@ color: #0273dc; text-decoration: none; } + + img { + max-width: 100%; + } } } diff --git a/docs/.dumi/components/Contributing/index.tsx b/docs/.dumi/components/Contributing/index.tsx index 00f8cff895da..1bdca3fdc9cc 100644 --- a/docs/.dumi/components/Contributing/index.tsx +++ b/docs/.dumi/components/Contributing/index.tsx @@ -16,7 +16,6 @@ export const Contributing = () => { diff --git a/docs/.dumi/components/Hero/index.less b/docs/.dumi/components/Hero/index.less index ee58335c5fca..106cbe170de1 100644 --- a/docs/.dumi/components/Hero/index.less +++ b/docs/.dumi/components/Hero/index.less @@ -1,5 +1,5 @@ .hero { - height: 640px; + min-height: 640px; position: relative; :global { @@ -122,3 +122,71 @@ } } } + +@media (max-width: 768px){ + .hero{ + :global{ + .bg{ + height: 100%; + background-repeat: repeat; + } + .wrapper{ + flex-wrap: wrap; + justify-content: center; + padding-bottom: 40px; + .left{ + padding-top: 40px; + padding-left: 0; + .bigLogo{ + margin: 0 auto; + width: 300px; + height: 139px; + background-size: 100% auto; + } + .actions{ + margin-top: 40px; + flex-wrap:wrap; + justify-content: center; + .button{ + margin-left: 0; + width: 120px; + height: 40px; + line-height: 40px; + font-size: 16px; + } + .githubStar{ + font-size: 12px; + line-height: 40px; + &::before{ + height: 40px; + } + } + } + } + .right{ + padding-top: 40px; + margin-right: 0; + .bigSlogan1{ + width: 200px; + height: 65px; + background-size: 100% auto; + } + .bigSlogan2{ + width: 300px; + height: 49px; + background-size: 100% auto; + } + .slogan{ + font-size: 20px; + width: auto; + } + .bow{ + width: 330px; + height: 168px; + background-size: 100% auto; + } + } + } + } + } +} diff --git a/docs/docs/docs/api/api.en-US.md b/docs/docs/docs/api/api.en-US.md index b3b99b46e91b..789ec30069fc 100644 --- a/docs/docs/docs/api/api.en-US.md +++ b/docs/docs/docs/api/api.en-US.md @@ -187,7 +187,8 @@ Type definition is as follows: ```ts declare function Link(props: { - prefetch?: boolean; + prefetch?: boolean | 'intent' | 'render' | 'viewport' | 'none'; + prefetchTimeout?: number; to: string | Partial<{ pathname: string; search: string; hash: string }>; replace?: boolean; state?: any; @@ -207,7 +208,7 @@ function IndexPage({ user }) { `` supports relative path navigation; `` does not do routing navigation and is equivalent to the jump behavior of ``. -If `prefetch` is enabled, then when the user hovers over the component, Umi will automatically start preloading the component js files and data for the routing jump. (Note: Use this feature when `routePrefetch` and `manifest` are enabled) +If `prefetch` is enabled, then when the user hovers over the component, Umi will automatically start preloading the component js files and data for the routing jump. (Note: Use this feature when `routePrefetch` is enabled) ### matchPath diff --git a/docs/docs/docs/api/api.md b/docs/docs/docs/api/api.md index 4139c76bbb32..dfe941a6a055 100644 --- a/docs/docs/docs/api/api.md +++ b/docs/docs/docs/api/api.md @@ -186,7 +186,8 @@ unlisten(); ```ts declare function Link(props: { - prefetch?: boolean; + prefetch?: boolean | 'intent' | 'render' | 'viewport' | 'none'; + prefetchTimeout?: number; to: string | Partial<{ pathname: string; search: string; hash: string }>; replace?: boolean; state?: any; @@ -206,7 +207,7 @@ function IndexPage({ user }) { `` 支持相对路径跳转;`` 不做路由跳转,等同于 `` 的跳转行为。 -若开启了 `prefetch` 则当用户将鼠标放到该组件上方时,Umi 就会自动开始进行跳转路由的组件 js 文件和数据预加载。(注:使用此功能请同时开启 `routePrefetch` 和 `manifest` 配置) +若开启了 `prefetch` 则当用户将鼠标放到该组件上方时,Umi 就会自动开始进行跳转路由的组件 js 文件和数据预加载。(注:使用此功能请开启 `routePrefetch` 配置) ### matchPath diff --git a/docs/docs/docs/api/config.en-US.md b/docs/docs/docs/api/config.en-US.md index 8b844153553c..2166ae697874 100644 --- a/docs/docs/docs/api/config.en-US.md +++ b/docs/docs/docs/api/config.en-US.md @@ -1304,7 +1304,7 @@ Configure how routes are loaded. Setting moduleType to 'cjs' will load route com ## routePrefetch -- Type: `boolean` +- Type: `{ defaultPrefetch: 'none' | 'intent' | 'render' | 'viewport', defaultPrefetchTimeout: number } | false` - Default: `false` Enable route preloading functionality. diff --git a/docs/docs/docs/api/config.md b/docs/docs/docs/api/config.md index fce4a49dc6a1..05b2ce19610a 100644 --- a/docs/docs/docs/api/config.md +++ b/docs/docs/docs/api/config.md @@ -1311,7 +1311,7 @@ proxy: { ## routePrefetch -- 类型:`boolean` +- 类型:`{ defaultPrefetch: 'none' | 'intent' | 'render' | 'viewport', defaultPrefetchTimeout: number } | false` - 默认值:`false` 启用路由预加载功能。 diff --git a/docs/docs/docs/api/runtime-config.en-US.md b/docs/docs/docs/api/runtime-config.en-US.md index 1b215766fbc3..6f2cae7cff79 100644 --- a/docs/docs/docs/api/runtime-config.en-US.md +++ b/docs/docs/docs/api/runtime-config.en-US.md @@ -100,7 +100,7 @@ The return value of `getInitialState()` will become the global initial state. Fo // src/app.ts import { fetchInitialData } from "@/services/initial"; -export async function () { +export async function getInitialState() { const initialData = await fetchInitialData(); return initialData; } diff --git a/docs/docs/docs/api/runtime-config.md b/docs/docs/docs/api/runtime-config.md index 1f64f54b6aca..ee1a53135094 100644 --- a/docs/docs/docs/api/runtime-config.md +++ b/docs/docs/docs/api/runtime-config.md @@ -98,7 +98,7 @@ export default { // src/app.ts import { fetchInitialData } from "@/services/initial"; -export async function () { +export async function getInitialState() { const initialData = await fetchInitialData(); return initialData; } diff --git a/docs/docs/docs/introduce/contributing.en-US.md b/docs/docs/docs/introduce/contributing.en-US.md index 22549218dd3f..fee6c9b249b8 100644 --- a/docs/docs/docs/introduce/contributing.en-US.md +++ b/docs/docs/docs/introduce/contributing.en-US.md @@ -14,9 +14,11 @@ translated_at: '2024-03-17T09:56:34.842Z' Developing Umi requires Node.js 18+ and `pnpm` v8. -It is recommended to use [`nvm`](https://github.com/nvm-sh/nvm) to manage Node.js versions to avoid permission issues and easily switch between Node.js versions. Windows developers can use [`nvm-windows`](https://github.com/coreybutler/nvm-windows). +It's recommended to use [Volta](https://volta.sh/) to manage the node and pnpm version. And you need to set the `VOLTA_FEATURE_PNPM` environment variable to enable pnpm support. -Install `pnpm` via one of the methods on its [official website](https://pnpm.io/installation). +```bash +export VOLTA_FEATURE_PNPM=1 +``` ### Clone the Project diff --git a/docs/docs/docs/introduce/contributing.md b/docs/docs/docs/introduce/contributing.md index 164c7f602fe5..bca8fa09b2ee 100644 --- a/docs/docs/docs/introduce/contributing.md +++ b/docs/docs/docs/introduce/contributing.md @@ -13,9 +13,11 @@ toc: content 开发 Umi 需要 Node.js 18+ 和 `pnpm` v8。 -推荐使用 [`nvm`](https://github.com/nvm-sh/nvm) 管理 Node.js,避免权限问题的同时,还能够随时切换当前使用的 Node.js 的版本。在 Windows 系统下的开发者可以使用 [`nvm-windows`](https://github.com/coreybutler/nvm-windows)。 +推荐使用 [Volta](https://volta.sh/) 来管理 Node.js 和 pnpm 版本。并且需要设置 `VOLTA_FEATURE_PNPM` 环境变量来启用 pnpm 支持。 -在 `pnpm` 的[官网](https://pnpm.io/installation)选择一种方式安装即可。 +```bash +export VOLTA_FEATURE_PNPM=1 +``` ### Clone 项目 diff --git a/docs/docs/docs/max/charts.md b/docs/docs/docs/max/charts.md index 492b0c31765e..0099e79e1bfc 100644 --- a/docs/docs/docs/max/charts.md +++ b/docs/docs/docs/max/charts.md @@ -27,7 +27,7 @@ pnpm install @ant-design/plots 在下面的使用示例中,我们将最小化引入。 -您也可以直接阅读 Ant Design Charts 完整的[上手文档](https://charts.ant.design/zh/docs/manual/getting-started)和[图表示例](https://charts.ant.design/zh/examples/gallery)。 +您也可以直接阅读 Ant Design Charts 完整的[上手文档](https://ant-design-charts.antgroup.com/manual/getting-started)和[图表示例](https://ant-design-charts.antgroup.com/examples)。 ### 曲线图 diff --git a/docs/docs/docs/max/data-flow.en-US.md b/docs/docs/docs/max/data-flow.en-US.md index 48ad620e9d07..17eb8ef6a47b 100644 --- a/docs/docs/docs/max/data-flow.en-US.md +++ b/docs/docs/docs/max/data-flow.en-US.md @@ -8,6 +8,33 @@ translated_at: '2024-03-18T00:49:20.502Z' `@umi/max` has a built-in **data flow management** [plugin](https://github.com/umijs/umi/blob/master/packages/plugins/src/model.ts), which is a lightweight data management solution based on the `hooks` paradigm. It can be used to manage global shared data in Umi projects. +## Configuration + +e.g. + +```ts +export default { + model: { + extraModels: ['src/models/userModel.ts'], + sort: (a, b) => a.namespace.localeCompare(b.namespace), + }, +}; +``` + +### extraModels + +- Type: `string[]` +- Default: `[]` + +Configure `extraModels` to automatically add these Model files to the data stream management. + +### sort + +- Type: `(a: Model, b: Model) => number` +- Default: `(a, b) => a.namespace.localeCompare(b.namespace)` + +Configure `sort` to sort the Model based on the return value of the `sort` function. + ## Getting Started ### Creating a Model @@ -220,7 +247,7 @@ For specific usage, please refer to the [micro-frontend's parent-child communica // src/components/AdminInfo/index.tsx import { useModel } from 'umi'; -export default function Page() { +export default () => { const { user, fetchUser } = useModel('adminModel', (model) => ({ user: model.admin, fetchUser: model.fetchAdmin, diff --git a/docs/docs/docs/max/data-flow.md b/docs/docs/docs/max/data-flow.md index 1ce7aa4144d7..b703574917f1 100644 --- a/docs/docs/docs/max/data-flow.md +++ b/docs/docs/docs/max/data-flow.md @@ -7,6 +7,33 @@ toc: content `@umi/max` 内置了**数据流管理**[插件](https://github.com/umijs/umi/blob/master/packages/plugins/src/model.ts),它是一种基于 `hooks` 范式的轻量级数据管理方案,可以在 Umi 项目中管理全局的共享数据。 +## 配置 + +e.g. + +```ts +export default { + model: { + extraModels: ['src/models/userModel.ts'], + sort: (a, b) => a.namespace.localeCompare(b.namespace), + }, +}; +``` + +### extraModels + +- Type: `string[]` +- Default: `[]` + +配置 `extraModels` 后,插件会自动将这些 Model 文件添加到数据流管理中。 + +### sort + +- Type: `(a: Model, b: Model) => number` +- Default: `(a, b) => a.namespace.localeCompare(b.namespace)` + +配置 `sort` 后,插件会根据 `sort` 函数返回的值对 Model 进行排序。 + ## 开始使用 ### 创建 Model @@ -29,7 +56,7 @@ Model 文件允许使用 `.(tsx|ts|jsx|js)` 四种后缀格式,**命名空间 ```ts // src/models/userModel.ts -export default function Page() { +export default () => { const user = { username: 'umi', }; diff --git a/docs/docs/docs/max/dva.en-US.md b/docs/docs/docs/max/dva.en-US.md index 1504bc32848b..d4a89c65bc77 100644 --- a/docs/docs/docs/max/dva.en-US.md +++ b/docs/docs/docs/max/dva.en-US.md @@ -340,4 +340,4 @@ Since the underlying layer of dva is based on redux, you can install redux's [de ## References -- [dva official website](https://dvajs.com/) +- [dva official website](https://dva.mxlab.top/) diff --git a/docs/docs/docs/max/dva.md b/docs/docs/docs/max/dva.md index a0ce5007371d..0a5b1d295144 100644 --- a/docs/docs/docs/max/dva.md +++ b/docs/docs/docs/max/dva.md @@ -338,4 +338,4 @@ dva 的底层是基于 redux,所以你可以安装 redux 的[开发者工具]( ## 参考文章 -- [dva 官网](https://dvajs.com/) +- [dva 官网](https://dva.mxlab.top/) diff --git a/lerna.json b/lerna.json index f3df26ee0765..afca2bff14ab 100644 --- a/lerna.json +++ b/lerna.json @@ -1,4 +1,4 @@ { - "version": "4.3.35", + "version": "4.4.4", "workspaces": ["packages/*"] } diff --git a/package.json b/package.json index 23501db0a4e4..e14b2397af7b 100644 --- a/package.json +++ b/package.json @@ -123,6 +123,10 @@ "node": ">=14", "pnpm": "^8.11.0" }, + "volta": { + "node": "20.18.1", + "pnpm": "8.15.9" + }, "//": { "why-overrides-parcel-watcher": "https://github.com/parcel-bundler/watcher/issues/156", "why-overrides-browserslist": "See scripts/bundleDeps.ts" diff --git a/packages/ast/package.json b/packages/ast/package.json index 356b9a54f528..4a548ae5864e 100644 --- a/packages/ast/package.json +++ b/packages/ast/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/ast", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/ast", "homepage": "https://github.com/umijs/umi/tree/master/packages/ast#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/babel-preset-umi/package.json b/packages/babel-preset-umi/package.json index 528eee49b6ba..5eba5e1dfff7 100644 --- a/packages/babel-preset-umi/package.json +++ b/packages/babel-preset-umi/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/babel-preset-umi", - "version": "4.3.35", + "version": "4.4.4", "description": "Official babel preset for umi.", "homepage": "https://github.com/umijs/umi/tree/master/packages/babel-preset-umi#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/bundler-esbuild/package.json b/packages/bundler-esbuild/package.json index c06d12841953..7ae1fd9b4cbb 100644 --- a/packages/bundler-esbuild/package.json +++ b/packages/bundler-esbuild/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/bundler-esbuild", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/bundler-esbuild", "homepage": "https://github.com/umijs/umi/tree/master/packages/bundler-esbuild#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/bundler-utils/package.json b/packages/bundler-utils/package.json index 6886182f719a..c693ea8e6aa2 100644 --- a/packages/bundler-utils/package.json +++ b/packages/bundler-utils/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/bundler-utils", - "version": "4.3.35", + "version": "4.4.4", "homepage": "https://github.com/umijs/umi/tree/master/packages/bundler-utils#readme", "bugs": "https://github.com/umijs/umi/issues", "repository": { diff --git a/packages/bundler-vite/package.json b/packages/bundler-vite/package.json index 7109ff8f5dfb..5e4324d53db6 100644 --- a/packages/bundler-vite/package.json +++ b/packages/bundler-vite/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/bundler-vite", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/bundler-vite", "homepage": "https://github.com/umijs/umi/tree/master/packages/bundler-vite#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/bundler-webpack/compiled/webpack/package.json b/packages/bundler-webpack/compiled/webpack/package.json index be9c8f1ffc8c..d965d392988d 100644 --- a/packages/bundler-webpack/compiled/webpack/package.json +++ b/packages/bundler-webpack/compiled/webpack/package.json @@ -1,5 +1,6 @@ { "name": "webpack", + "version": "5.88.2", "author": "Tobias Koppers @sokra", "types": "types.d.ts" } diff --git a/packages/bundler-webpack/package.json b/packages/bundler-webpack/package.json index d183a14e4fdb..dd4fba7a45e9 100644 --- a/packages/bundler-webpack/package.json +++ b/packages/bundler-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/bundler-webpack", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/bundler-webpack", "homepage": "https://github.com/umijs/umi/tree/master/packages/bundler-webpack#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/bundler-webpack/src/config/config.ts b/packages/bundler-webpack/src/config/config.ts index 949b175e2f3e..6d22a6530b77 100644 --- a/packages/bundler-webpack/src/config/config.ts +++ b/packages/bundler-webpack/src/config/config.ts @@ -67,7 +67,7 @@ export async function getConfig(opts: IOpts): Promise { const config = new Config(); userConfig.targets ||= DEFAULT_BROWSER_TARGETS; // normalize inline limit - userConfig.inlineLimit = parseInt(userConfig.inlineLimit || '10000', 10); + userConfig.inlineLimit = parseInt(userConfig.inlineLimit ?? '10000', 10); const useHash = !!(opts.hash || (userConfig.hash && !isDev)); const applyOpts = { name: opts.name, diff --git a/packages/core/package.json b/packages/core/package.json index 60b1477f1cd9..1462b0f31683 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/core", - "version": "4.3.35", + "version": "4.4.4", "homepage": "https://github.com/umijs/umi/tree/master/packages/core#readme", "bugs": "https://github.com/umijs/umi/issues", "repository": { diff --git a/packages/create-umi/package.json b/packages/create-umi/package.json index 5a35eb243f97..645c9e012ee2 100644 --- a/packages/create-umi/package.json +++ b/packages/create-umi/package.json @@ -1,6 +1,6 @@ { "name": "create-umi", - "version": "4.3.35", + "version": "4.4.4", "description": "create-umi", "homepage": "https://github.com/umijs/umi/tree/master/packages/create-umi#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/lint/package.json b/packages/lint/package.json index 3ea92b05eb4b..3ff2454d71c5 100644 --- a/packages/lint/package.json +++ b/packages/lint/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/lint", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/lint", "homepage": "https://github.com/umijs/umi/tree/master/packages/lint#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/max/package.json b/packages/max/package.json index 3f5fb2ed0245..3691905c9234 100644 --- a/packages/max/package.json +++ b/packages/max/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/max", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/max", "homepage": "https://github.com/umijs/umi/tree/master/packages/max#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/mfsu/package.json b/packages/mfsu/package.json index 559779b6e8dd..33df4d4fc009 100644 --- a/packages/mfsu/package.json +++ b/packages/mfsu/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/mfsu", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/mfsu", "homepage": "https://github.com/umijs/umi/tree/master/packages/mfsu#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/plugin-docs/package.json b/packages/plugin-docs/package.json index 8c40157331bc..b7c84dd1fb52 100644 --- a/packages/plugin-docs/package.json +++ b/packages/plugin-docs/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/plugin-docs", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/plugin-docs", "homepage": "https://github.com/umijs/umi/tree/master/packages/plugin-docs#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/plugin-run/package.json b/packages/plugin-run/package.json index f9efbe1fdb5e..db8323afc073 100644 --- a/packages/plugin-run/package.json +++ b/packages/plugin-run/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/plugin-run", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/plugin-run", "homepage": "https://github.com/umijs/umi/tree/master/packages/plugin-run#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/plugins/package.json b/packages/plugins/package.json index c93e3ba43e31..ac4213fae2e4 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/plugins", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/plugins", "homepage": "https://github.com/umijs/umi/tree/master/packages/plugins#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/plugins/src/model.ts b/packages/plugins/src/model.ts index d377b4f39e8f..8259e20f0f07 100644 --- a/packages/plugins/src/model.ts +++ b/packages/plugins/src/model.ts @@ -13,6 +13,7 @@ export default (api: IApi) => { return zod .object({ extraModels: zod.array(zod.string()), + sort: zod.function().optional(), }) .partial(); }, @@ -22,6 +23,9 @@ export default (api: IApi) => { api.onGenerateFiles(async () => { const models = await getAllModels(api); + if (api.userConfig.model?.sort) { + models.sort(api.userConfig.model.sort); + } // model.ts api.writeTmpFile({ diff --git a/packages/preset-umi/package.json b/packages/preset-umi/package.json index fb2ce25318a1..d6d6072487fc 100644 --- a/packages/preset-umi/package.json +++ b/packages/preset-umi/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/preset-umi", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/preset-umi", "homepage": "https://github.com/umijs/umi/tree/master/packages/preset-umi#readme", "bugs": "https://github.com/umijs/umi/issues", @@ -30,7 +30,7 @@ "@umijs/ast": "workspace:*", "@umijs/babel-preset-umi": "workspace:*", "@umijs/bundler-esbuild": "workspace:*", - "@umijs/bundler-mako": "0.9.7", + "@umijs/bundler-mako": "0.11.1", "@umijs/bundler-utils": "workspace:*", "@umijs/bundler-vite": "workspace:*", "@umijs/bundler-webpack": "workspace:*", diff --git a/packages/preset-umi/src/commands/dev/plugins/ViteHtmlPlugin.ts b/packages/preset-umi/src/commands/dev/plugins/ViteHtmlPlugin.ts index 3561d51f0888..7f236f6ac9b1 100644 --- a/packages/preset-umi/src/commands/dev/plugins/ViteHtmlPlugin.ts +++ b/packages/preset-umi/src/commands/dev/plugins/ViteHtmlPlugin.ts @@ -21,7 +21,9 @@ export default function ViteHtmlPlugin(api: IApi): Plugin { try { // 处理通用html const viteScripts: IOpts['scripts'] = [ - api.appData.hasSrcDir ? '/src/.umi/umi.ts' : '/.umi/umi.ts', + `${api.appData.hasSrcDir ? '/src' : ''}/.${ + api.service.frameworkName + }/umi.ts`, ]; const markupArgs = (await getMarkupArgs({ api })) as any; diff --git a/packages/preset-umi/src/features/routePrefetch/routePrefetch.ts b/packages/preset-umi/src/features/routePrefetch/routePrefetch.ts index dffb8f526368..173e21f45e30 100644 --- a/packages/preset-umi/src/features/routePrefetch/routePrefetch.ts +++ b/packages/preset-umi/src/features/routePrefetch/routePrefetch.ts @@ -4,13 +4,27 @@ export default (api: IApi) => { api.describe({ config: { schema({ zod }) { - return zod.object({}); + return zod.object({ + defaultPrefetch: zod + .enum(['none', 'intent', 'render', 'viewport']) + .optional(), + defaultPrefetchTimeout: zod.number().optional(), + }); }, }, enableBy: api.EnableBy.config, }); api.addEntryCodeAhead(() => { - return `if(typeof window !== 'undefined') window.__umi_route_prefetch__ = true;`; + return `if(typeof window !== 'undefined') window.__umi_route_prefetch__ = + { + defaultPrefetch: ${JSON.stringify( + api.config.routePrefetch.defaultPrefetch || 'none', + )}, + defaultPrefetchTimeout: ${JSON.stringify( + api.config.routePrefetch.defaultPrefetchTimeout || 50, + )}, + }; + `; }); }; diff --git a/packages/preset-vue/package.json b/packages/preset-vue/package.json index 9f92c6327e75..6f0ba793e973 100644 --- a/packages/preset-vue/package.json +++ b/packages/preset-vue/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/preset-vue", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/preset-vue", "homepage": "https://github.com/umijs/umi/tree/master/packages/preset-vue#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/renderer-react/package.json b/packages/renderer-react/package.json index 6e16711eeae7..5710f505e626 100644 --- a/packages/renderer-react/package.json +++ b/packages/renderer-react/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/renderer-react", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/renderer-react", "homepage": "https://github.com/umijs/umi/tree/master/packages/renderer-react#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/renderer-react/src/link.tsx b/packages/renderer-react/src/link.tsx index c518fc978d15..3a44e6ab8c23 100644 --- a/packages/renderer-react/src/link.tsx +++ b/packages/renderer-react/src/link.tsx @@ -1,27 +1,111 @@ -import React, { PropsWithChildren } from 'react'; +import React, { PropsWithChildren, useLayoutEffect } from 'react'; import { Link, LinkProps } from 'react-router-dom'; import { useAppData } from './appContext'; +import { useIntersectionObserver } from './useIntersectionObserver'; -export function LinkWithPrefetch( - props: PropsWithChildren< - { - prefetch?: boolean; - } & LinkProps & - React.RefAttributes - >, -) { - const { prefetch, ...linkProps } = props; - const appData = useAppData(); - const to = typeof props.to === 'string' ? props.to : props.to?.pathname; - // compatible with old code - // which to might be undefined - if (!to) return null; - return ( - prefetch && to && appData.preloadRoute?.(to)} - {...linkProps} - > - {props.children} - - ); +function useForwardedRef(ref?: React.ForwardedRef) { + const innerRef = React.useRef(null); + React.useEffect(() => { + if (!ref) return; + if (typeof ref === 'function') { + ref(innerRef.current); + } else { + ref.current = innerRef.current; + } + }); + return innerRef; } + +export const LinkWithPrefetch = React.forwardRef( + ( + props: PropsWithChildren< + { + prefetch?: boolean | 'intent' | 'render' | 'viewport' | 'none'; + prefetchTimeout?: number; + } & LinkProps & + React.RefAttributes + >, + forwardedRef, + ) => { + const { prefetch: prefetchProp, ...linkProps } = props; + const { defaultPrefetch, defaultPrefetchTimeout } = (typeof window !== + 'undefined' && // @ts-ignore + window.__umi_route_prefetch__) || { + defaultPrefetch: 'none', + defaultPrefetchTimeout: 50, + }; + + const prefetch = + (prefetchProp === true + ? 'intent' + : prefetchProp === false + ? 'none' + : prefetchProp) || defaultPrefetch; + if (!['intent', 'render', 'viewport', 'none'].includes(prefetch)) { + throw new Error( + `Invalid prefetch value ${prefetch} found in Link component`, + ); + } + const appData = useAppData(); + const to = typeof props.to === 'string' ? props.to : props.to?.pathname; + const hasRenderFetched = React.useRef(false); + const ref = useForwardedRef(forwardedRef); + // prefetch intent + const handleMouseEnter = (e: React.MouseEvent) => { + if (prefetch !== 'intent') return; + const eventTarget = (e.target || {}) as HTMLElement & { + preloadTimeout?: NodeJS.Timeout | null; + }; + if (eventTarget.preloadTimeout) return; + eventTarget.preloadTimeout = setTimeout(() => { + eventTarget.preloadTimeout = null; + appData.preloadRoute?.(to!); + }, props.prefetchTimeout || defaultPrefetchTimeout); + }; + const handleMouseLeave = (e: React.MouseEvent) => { + if (prefetch !== 'intent') return; + const eventTarget = (e.target || {}) as HTMLElement & { + preloadTimeout?: NodeJS.Timeout | null; + }; + if (eventTarget.preloadTimeout) { + clearTimeout(eventTarget.preloadTimeout); + eventTarget.preloadTimeout = null; + } + }; + + // prefetch render + useLayoutEffect(() => { + if (prefetch === 'render' && !hasRenderFetched.current) { + appData.preloadRoute?.(to!); + hasRenderFetched.current = true; + } + }, [prefetch, to]); + + // prefetch viewport + useIntersectionObserver( + ref as React.RefObject, + (entry) => { + if (entry?.isIntersecting) { + appData.preloadRoute?.(to!); + } + }, + { rootMargin: '100px' }, + { disabled: prefetch !== 'viewport' }, + ); + + // compatible with old code + // which to might be undefined + if (!to) return null; + + return ( + } + {...linkProps} + > + {props.children} + + ); + }, +); diff --git a/packages/renderer-react/src/useIntersectionObserver.ts b/packages/renderer-react/src/useIntersectionObserver.ts new file mode 100644 index 000000000000..978f565a1be5 --- /dev/null +++ b/packages/renderer-react/src/useIntersectionObserver.ts @@ -0,0 +1,33 @@ +import React from 'react'; + +export function useIntersectionObserver( + ref: React.RefObject, + callback: (entry: IntersectionObserverEntry | undefined) => void, + intersectionObserverOptions: IntersectionObserverInit = {}, + options: { disabled?: boolean } = {}, +): IntersectionObserver | null { + // check if IntersectionObserver is available + if (typeof IntersectionObserver !== 'function') return null; + + const isIntersectionObserverAvailable = React.useRef( + typeof IntersectionObserver === 'function', + ); + const observerRef = React.useRef(null); + React.useEffect(() => { + if ( + !ref.current || + !isIntersectionObserverAvailable.current || + options.disabled + ) { + return; + } + observerRef.current = new IntersectionObserver(([entry]) => { + callback(entry); + }, intersectionObserverOptions); + observerRef.current.observe(ref.current); + return () => { + observerRef.current?.disconnect(); + }; + }, [callback, intersectionObserverOptions, options.disabled, ref]); + return observerRef.current; +} diff --git a/packages/renderer-vue/package.json b/packages/renderer-vue/package.json index d83a64e38cce..e7b92c9a6900 100644 --- a/packages/renderer-vue/package.json +++ b/packages/renderer-vue/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/renderer-vue", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/renderer-vue", "homepage": "https://github.com/umijs/umi/tree/master/packages/renderer-vue#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/server/package.json b/packages/server/package.json index c195b327e4d9..10be24333444 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/server", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/server", "homepage": "https://github.com/umijs/umi/tree/master/packages/server#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/testing/package.json b/packages/testing/package.json index 564e3a5f488c..684e9d10f560 100644 --- a/packages/testing/package.json +++ b/packages/testing/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/test", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/test", "homepage": "https://github.com/umijs/umi/tree/master/packages/testing#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/umi/package.json b/packages/umi/package.json index f72fc70f64fc..5a5699ebaeab 100644 --- a/packages/umi/package.json +++ b/packages/umi/package.json @@ -1,6 +1,6 @@ { "name": "umi", - "version": "4.3.35", + "version": "4.4.4", "description": "umi", "homepage": "https://github.com/umijs/umi/tree/master/packages/umi#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/packages/utils/package.json b/packages/utils/package.json index 7fded5d16b42..9af0d902fe51 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/utils", - "version": "4.3.35", + "version": "4.4.4", "homepage": "https://github.com/umijs/umi/tree/master/packages/utils#readme", "bugs": "https://github.com/umijs/umi/issues", "repository": { diff --git a/packages/zod2ts/package.json b/packages/zod2ts/package.json index bcc5f356f415..cbf3ea31f883 100644 --- a/packages/zod2ts/package.json +++ b/packages/zod2ts/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/zod2ts", - "version": "4.3.35", + "version": "4.4.4", "description": "@umijs/zod2ts", "homepage": "https://github.com/umijs/umi/tree/master/packages/zod2ts#readme", "bugs": "https://github.com/umijs/umi/issues", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 702d295b77f1..287751a4d3ad 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2435,8 +2435,8 @@ importers: specifier: workspace:* version: link:../bundler-esbuild '@umijs/bundler-mako': - specifier: 0.9.7 - version: 0.9.7 + specifier: 0.11.1 + version: 0.11.1 '@umijs/bundler-utils': specifier: workspace:* version: link:../bundler-utils @@ -18488,11 +18488,11 @@ packages: - supports-color dev: true - /@umijs/bundler-mako@0.9.7: - resolution: {integrity: sha512-RFaWLLIAhhsOwVySHYyrxK9jdb7vjj0DXZabyD+PVYbr9Sjy7aWzOuUykFKNegD793wbI26zeoovwrYmtbJstw==} + /@umijs/bundler-mako@0.11.1: + resolution: {integrity: sha512-8OKgKjvcCp6DXxiPkcT/oTaSx+VQnVQpCJxgKHuXA3l4zSY8BaeKGqnHMzEb5ZvgR0lylYKA+inpvKflcSdMOw==} dependencies: '@umijs/bundler-utils': 4.1.2 - '@umijs/mako': 0.9.7 + '@umijs/mako': 0.11.1 chalk: 4.1.2 compression: 1.7.4 connect-history-api-fallback: 2.0.0 @@ -18838,8 +18838,8 @@ packages: - typescript dev: true - /@umijs/mako-darwin-arm64@0.9.7: - resolution: {integrity: sha512-mOmhSuR0v0FpJ6jW2EDyvUbevQmrd54ly8vLO+L/Rv83GiOzlu7V97GwpW1kQUrNiN7jWiFy6inDhF2lQ1apnw==} + /@umijs/mako-darwin-arm64@0.11.1: + resolution: {integrity: sha512-GszLCLewkq/CuPkJ2/UUhULP/k30zMqlhygbfYshVRo6sSvjGfMAL/pB5IIMqsCcXKnmRuNCEawL4lX8rGUoKw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -18847,8 +18847,8 @@ packages: dev: false optional: true - /@umijs/mako-darwin-x64@0.9.7: - resolution: {integrity: sha512-Wf+oHQv/93M5/yzdkBK5nZBzuSde1lZB1kICVToriTW9UV7BnC8i0EFtUmerRBqLcE8cUX9jnRBoYZwO1jaotA==} + /@umijs/mako-darwin-x64@0.11.1: + resolution: {integrity: sha512-OmNATCaDtGy1sW5q9xkZqZkTkG+TyHrE4IJyqSB/0XN4EuYlsrsywT1IYAiRZ1B6FqsfBvDufF3+7rwhKFFVMg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -18856,8 +18856,8 @@ packages: dev: false optional: true - /@umijs/mako-linux-arm64-gnu@0.9.7: - resolution: {integrity: sha512-ZD2s5B38Gp8SIJENJ99PWhv/8+LbQiEAZTuT3fIdDOWvTvism3kCM82QwPsNOambVtCVHrbM5cAWLp8wfFcUoA==} + /@umijs/mako-linux-arm64-gnu@0.11.1: + resolution: {integrity: sha512-b/obD8RwBe+eY28G+T8C1DH8deRVmVnokKF7JdbYCF9t+UrzqJK4eZrKEOQ+a8aXC7dYfQNZvpSEmLwbxPJ9tA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -18865,8 +18865,8 @@ packages: dev: false optional: true - /@umijs/mako-linux-arm64-musl@0.9.7: - resolution: {integrity: sha512-OJCdq+zE/5QZwKYZH0zIB7fTckxUvCnFWgqq/oWY965A4P9JRDxIDcEp3nM1b18rUpGN799JVbbO1LRAco0Row==} + /@umijs/mako-linux-arm64-musl@0.11.1: + resolution: {integrity: sha512-jLjQ3ShisCj7x8h+uz/alXNfl1RpaanA8BPOGmbZLV6Mz8bE2/BXdDdo1YAd8/RwXZc4VdmPLGCzXW3+IyiGNg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -18874,8 +18874,8 @@ packages: dev: false optional: true - /@umijs/mako-linux-x64-gnu@0.9.7: - resolution: {integrity: sha512-RNgoO3Ux3fJ48W62G6ibktnQvdgTN0Nrj03iUJ4WWfbt2LuJwGfFw25aHVV53ylHSN+gRXe5PQJ7xyDXmaD/kA==} + /@umijs/mako-linux-x64-gnu@0.11.1: + resolution: {integrity: sha512-mdsb+/wbqu8nZ8qrS1fVsy8KbyxrPfjVlGB99n1KgsRKXXIV2Ze+K9cJCXW2AzEiGWuaobHyqT6hoskudPmthA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -18883,8 +18883,8 @@ packages: dev: false optional: true - /@umijs/mako-linux-x64-musl@0.9.7: - resolution: {integrity: sha512-bthSiiHZc5sNNLLK/ivSZ0KpUXGKR+eZwcKYa54L6AOy90GEbuY668lSJFP1+B20FC6pen0CNxko8OR6dgxB2A==} + /@umijs/mako-linux-x64-musl@0.11.1: + resolution: {integrity: sha512-rYKF9lvOhOu47+E3gbtXbDbq8oxwR/+t97FgyRvdqOWvqdVyH74aDNi30rg/XBrNq6E79f6KAbf/2oi2zrZfWA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -18892,8 +18892,8 @@ packages: dev: false optional: true - /@umijs/mako-win32-ia32-msvc@0.9.7: - resolution: {integrity: sha512-0S2HJNcMkDidK3QU2BgYFzXUi1phRDOyiT+bHcYyVJR4vARSb9GwrgAkooNaUxy3vn1x4dmNw/JL/4jxxtQ6jw==} + /@umijs/mako-win32-ia32-msvc@0.11.1: + resolution: {integrity: sha512-krPtRgUNckttWNX1Axrm1qZ8aHeL3IU/B/GLd4iXgMVwpxMHdeRubeMXCNv9TCeatOLGBvGkpAI2NyM76q+3lg==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -18901,8 +18901,8 @@ packages: dev: false optional: true - /@umijs/mako-win32-x64-msvc@0.9.7: - resolution: {integrity: sha512-g6ocRGSg2hLdl8gmqF3QgC7tFwurOvjY77HJzjJ0DJx3w43UwgmAkn+S6LrPwXqwwL53dldl8x1arkdcfxJEQA==} + /@umijs/mako-win32-x64-msvc@0.11.1: + resolution: {integrity: sha512-5CQ66jhY/6R0D1UoFKrxgM+mpKcZlCApS5uc0jh2mlw0poiHRcyspdOIkw73eKIz7oQgzjDjEM3a/fh7bOIofQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -18910,8 +18910,8 @@ packages: dev: false optional: true - /@umijs/mako@0.9.7: - resolution: {integrity: sha512-pBpZ1vZ3tS+TeWs5x9dckFwHaZE15Wa2JYDaW79ynp+3N3dGXKIdqoFsKfYPo5Z1y78EaSbVJ4mdvLkvjb+U3g==} + /@umijs/mako@0.11.1: + resolution: {integrity: sha512-/NAEz2yDmKfrEoW10lXhy4Iul5bcjXXUgSYGglASwgeap+YY+jnqzRJdQ1LP0sGZMeaFr0rj5MLXtuqU5LMNVQ==} engines: {node: '>= 16'} hasBin: true dependencies: @@ -18929,14 +18929,14 @@ packages: semver: 7.6.2 yargs-parser: 21.1.1 optionalDependencies: - '@umijs/mako-darwin-arm64': 0.9.7 - '@umijs/mako-darwin-x64': 0.9.7 - '@umijs/mako-linux-arm64-gnu': 0.9.7 - '@umijs/mako-linux-arm64-musl': 0.9.7 - '@umijs/mako-linux-x64-gnu': 0.9.7 - '@umijs/mako-linux-x64-musl': 0.9.7 - '@umijs/mako-win32-ia32-msvc': 0.9.7 - '@umijs/mako-win32-x64-msvc': 0.9.7 + '@umijs/mako-darwin-arm64': 0.11.1 + '@umijs/mako-darwin-x64': 0.11.1 + '@umijs/mako-linux-arm64-gnu': 0.11.1 + '@umijs/mako-linux-arm64-musl': 0.11.1 + '@umijs/mako-linux-x64-gnu': 0.11.1 + '@umijs/mako-linux-x64-musl': 0.11.1 + '@umijs/mako-win32-ia32-msvc': 0.11.1 + '@umijs/mako-win32-x64-msvc': 0.11.1 dev: false /@umijs/max-plugin-openapi@2.0.3: