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: