umi4.js基本使用方法示例详解
作者:小前端大牛马
1.什么是umi?
Umi,中文发音为「乌米」,是可扩展的企业级前端应用框架。Umi 以路由为基础,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。然后配以生命周期完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。
2.umi的特性有哪些?
- 路由驱动:通过路由配置生成应用结构,支持动态路由、嵌套路由、权限路由等。
- 插件系统:通过插件扩展功能(如国际化、代码分割、API 请求、Ant Design 集成等)。
- 配置化:通过
config/config.js
或.umirc.ts
集中配置,灵活且可扩展。 - 按需加载:支持代码分割和懒加载,提升应用性能。
- 内置开发工具:提供热更新、路由跳转、插件调试等功能。
3.umi的优点
1、企业级,在安全性、稳定性、最佳实践、约束能力方面会考虑更多
2、插件化,啥都能改,Umi 本身也是由插件构成
3、MFSU,比 Vite 还快的 Webpack 打包方案
4、基于 React Router 6 的完备路由
5、默认最快的请求
6、SSR & SSG
7、稳定白盒性能好的 ESLint 和 Jest
8、React 18 的框架级接入
9、Monorepo 最佳实践
4.umi的基本使用
1. 安装与初始化
首先得有 node,并确保 node 版本是 18 或以上。
然后需要包管理工具。node 默认包含 npm,但也可以选择其他方案,
创建项目:
pnpm dlx create-umi@latest my-app ✔ Install the following package: create-umi? (Y/n) · true ✔ Pick Npm Client › pnpm ✔ Pick Npm Registry › taobao Write: .gitignore Write: .npmrc Write: .umirc.ts Copy: layouts/index.tsx Write: package.json Copy: pages/index.tsx Copy: pages/users.tsx Copy: pages/users/foo.tsx @ postinstall /private/tmp/sorrycc-vylwuW umi setup info - generate files //国内建议选 pnpm + taobao 源,速度提升明显。这一步会自动安装依赖,同时安装成功后会自动执行 umi setup 做一些文件预处理等工作。 /* 执行之后会在控制台会出现用户交互操作,按照提示来操作即可。 第一步是让你确定项目文件夹的名称,然后选择项目的模版。因为在Umi3中是没有集成一些插件的,很多的插件在项目创建之后在根据需要进行安装。但是Umi4变得更加方便了,直接在项目中集成插件,然后根据需要进行启用和关闭。 */
模板选项:
Simple App
:基础项目模板,纯净版的Umi,包含umi4文档上关于Guides下的所有功能,但是不包括Umi Max。。Ant Design Pro
:集成 Pro Layout 和权限系统的完整模板 ,包含Umi Max的完整功能,均可通过在.umirc.ts 或 config/config.ts中插拔式配置
2.启动项目
执行 pnpm dev
命令,
pnpm dev ╔═════════════════════════════════════════════════════╗ ║ App listening at: ║ ║ > Local: https://127.0.0.1:8000 ║ ready - ║ > Network: https://192.168.1.1:8000 ║ ║ ║ ║ Now you can open browser with the above addresses👆 ║ ╚═════════════════════════════════════════════════════╝ event - compiled successfully in 1121 ms (388 modules) event - MFSU compiled successfully in 1308 ms (875 modules)
在浏览器里打开 http://localhost:8000/,能看到以下界面,
3.启用 Prettier(可选)
如果需要用 prettier 做项目代码的自动格式化,执行 pnpm umi g
,
pnpm umi g ✔ Pick generator type › Enable Prettier -- Enable Prettier info - Write package.json info - Write .prettierrc info - Write .prettierignore info - Install dependencies with pnpm
4.umi的目录结构
这里罗列了 Umi 项目中约定(或推荐)的目录结构,在项目开发中,请遵照这个目录结构组织代码。
├── config/ // 配置目录(核心) │ └── config.ts // 主配置文件(支持多环境配置) ├── dist/ // 构建产物目录(默认输出路径) ├── mock/ // 模拟数据目录 │ └── app.ts|tsx // Mock 数据定义入口 ├── src/ // 源码核心目录(开发主区域) │ ├── .umi/ // 临时文件目录(框架生成,勿手动修改) │ ├── .umi-production/ // 生产环境临时文件(构建时生成) │ ├── layouts/ // 全局布局目录(约定式) │ │ ├── BasicLayout.tsx // 基础布局组件 │ │ └── index.less // 布局样式 │ ├── pages/ //页面组件目录(约定式路由核心) │ │ ├── index.less // 页面样式 │ │ └── index.tsx // 页面组件(自动映射为路由) │ ├── models/ // 数据模型目录(推荐) │ ├── utils/ // 工具函数目录(推荐) │ ├── services/ // 服务目录api接口配置(推荐) │ ├── app.tsx // 运行时配置入口(扩展生命周期) │ └── global.less // 全局样式覆盖 └── public/ // 静态资源目录(直接拷贝至构建产物) └── favicon.ico // 网站图标(需与配置路径匹配)
1. 目录结构详解
package.json:与 Umi 3 不同,Umi 4 不会自动注册 package.json
中以 @umijs/preset-
、@umijs/plugin-
、umi-preset-
和 umi-plugin-
开头的插件、预设,若你需要自定义额外的插件、预设,需要手动配置到 plugins 。
.umirc.ts:与 config/config.ts
文件功能相同,2 选 1 。.umirc.ts
文件优先级较高,区别是你可以单独在一个 config
文件夹下集中管理所有的配置,保持项目根目录整洁。包含 Umi 所有非运行时配置(运行时配置一般定义于 app.ts)
dist 目录:执行 umi build
后产物的默认输出文件夹。可通过 outputPath 配置修改产物输出文件夹。
mock 目录:存放 mock 文件,此目录下所有 .ts
/ .js
文件会被 mock 服务加载,从而提供模拟数据,使用方法详见 Mock 。
public 目录:存放固定的静态资源,如存放 public/image.png
,则开发时可以通过 /image.png
访问到,构建后会被拷贝到输出文件夹。
.umi 目录:.umi/
为临时目录,禁止手动修改(需加入 .gitignore
)。默认已在 .gitignore
被忽略。dev 时的临时文件目录,比如入口文件、路由等,都会被临时生成到这里。
.env:
环境变量文件(如 API_URL=http://api.example.com
)
app.[ts|tsx]:运行时配置文件,可以在这里扩展运行时的能力,比如修改路由、修改 render 方法等。运行时配置带来的逻辑会在浏览器中运行,因此当有远程配置、动态内容时,这些我们在本地开发时还不确定,不能写死,所以需要在浏览器实际运行项目时动态获取他们。
// 示例:全局错误处理 export function onError(error: Error) { console.error('全局错误:', error); }
global.(j|t)sx:全局前置脚本文件。Umi 区别于其他前端框架,没有显式的程序主入口(如 src/index.ts
),所以当你有需要在应用前置、全局运行的逻辑时,优先考虑写入 global.ts
。
//全局数据共享与状态管理:通过 useModel 实现跨组件的数据共享,替代部分 dva 场景 // src/models/global.tsx import { useState } from 'react'; export default () => { const [globalData, setGlobalData] = useState({}); return { globalData, setGlobalData }; };
文件 | 作用域 | 典型场景 |
---|---|---|
app.ts | 运行时环境(应用实例) | 全局状态初始化、路由拦截、错误边界处理 |
global.tsx | 全局数据共享或类型声明 | 跨组件状态管理、全局类型定义 |
当你需要添加全局 Context 、修改应用运行时,请使用 app.tsx 。
2.注意
config/
和 src/pages/
为框架识别目录,不可更名或删除。
可新增 src/components/
、src/hooks/
等目录管理公共组件或逻辑。
通过 app.tsx
扩展运行时配置(如权限拦截、全局状态注入)
5.umi的环境变量
1. 基础环境变量
定义方式:
在项目根目录创建.env
文件,格式为KEY=VALUE
:.env
:基础配置(所有环境生效).env.local
:本地覆盖配置(优先级高于.env
).env.production
:生产环境专用变量
支持变量嵌套(如CONCAT=$FOO$BAR)
# .env API_URL=http://api.example.com NODE_ENV=development
- 使用方式:
在代码中通过 process.env.KEY
访问:
// src/services/api.ts const BASE_URL = process.env.API_URL;
2.多环境配置文件
通过 UMI_ENV 指定环境,加载对应配置:
//启动预发布环境 UMI_ENV=staging pnpm dev
对应加载文件优先级:config.ts
→ config.${UMI_ENV}.ts
→ config.${dev|prod|test}.ts
→ config.local.ts
3.运行时变量注入
在config/config.ts
中使用define
字段暴露变量至前端代码:
前端通过process.env.API_SECRET读取值(需注意敏感信息需加密处理)
export default defineConfig({ define: { 'process.env.UMI_ENV': process.env.UMI_ENV || 'dev', 'process.env.API_URL': '"https://prod.example.com"', // 需要转义双引号 'process.env.API_SECRET': 'your_key_here' } });
4. 构建时注入变量
通过命令行动态覆盖环境变量:
在启动或构建命令中直接传递变量,优先级最高,用于临时调试场景(如快速修改开发服务器端口) :
API_URL=http://test.example.com umi build // 修改端口示例(跨平台推荐 cross-env) cross-env PORT=3000 pnpm dev
5.多环境管理规则
保留名称限制
dev/test/prod
为框架保留值,手动设置无效,需改用自定义名称(如staging
、pre
)触发多环境配置加载。配置文件示例
开发环境配置(config/config.staging.ts
):
export default defineConfig({ define: { 'process.env.API_HOST': 'https://staging.api.com' }, proxy: { '/api': { target: 'http://staging.server' } } });
6.umi的约定式路由
1.基本规则
1.文件路径映射路由
Umi4 根据 src/pages
目录下的文件结构自动生成路由配置:
pages/ ├── index.tsx → path: '/' ├── about.tsx → path: '/about' └── users/ └── index.tsx → path: '/users'
2.嵌套路由:
子目录会生成嵌套路径:
pages/ └── users/ ├── index.tsx → path: '/users' └── list.tsx → path: '/users/list'
生成的路由配置为:
[ { path: '/users', component: '@/pages/users/index' }, { path: '/users/list', component: '@/pages/users/list' }, ]
3.动态路由
动态参数路由:
使用 [参数名]
包裹文件或目录,生成动态参数路径,组件内通过 props.match.params
获取参数::
pages/ └── users/ └── [id].tsx → path: '/users/:id'
// /pages/users/[id].jsx export default (props) => { const { id } = props.match.params; // 访问 /users/123 时 id=123 return <div>{id}</div>; };
可选动态参数路由:
使用 [参数名$]
标记为可选参数:
//在动态路由定义中,/pages/user/[id$].jsx 表示 id 为可选,访问 /user 和 /user/123 均可匹配该路由 pages/ └── users/ └── [id$].tsx → path: '/users/:id?'
4. 嵌套路由与布局
局部嵌套路由:
在目录中添加 _layout.tsx
文件,作为该目录的布局容器,并通过 props.children
渲染子路由:
pages/ └── users/ ├── _layout.tsx → 父路由布局 ├── index.tsx → path: '/users' └── detail/[id].tsx → path: '/users/detail/:id'
生成的路由配置为:
{ path: '/users', component: '@/pages/users/_layout', routes: [ { path: '/users', component: '@/pages/users/index' }, { path: '/users/detail/:id', component: '@/pages/users/detail/[id]' }, ], }
全局布局:
在 src/layouts/index.tsx
定义全局布局,包裹所有路由组件。
[ { exact: false, path: '/', component: '@/layouts/index', routes: [ { exact: true, path: '/', component: '@/pages/index' }, { exact: true, path: '/users', component: '@/pages/users' }, ], }, ]
// /src/layouts/index.jsx export default ({ children }) => { return ( <div> <Header /> {children} <Footer /> </div> ); };
不同的全局布局
你可能需要针对不同路由输出不同的全局 layout,Umi 不支持这样的配置,但你仍可以在 src/layouts/index.tsx
中对 location.path
做区分,渲染不同的 layout 。
比如想要针对 /login
输出简单布局
export default function(props) { if (props.location.pathname === '/login') { return <SimpleLayout>{ props.children }</SimpleLayout> } return ( <> <Header /> { props.children } <Footer /> </> ); }
5.404 页面
在 src/pages/404.tsx
中定义自定义 404 页面,开发模式下需通过 /404
显式访问。
注意:以下文件或目录会被 忽略,不生成路由
- 以
.
或_
开头的文件或目录 - 以
d.ts
结尾的类型定义文件 - 以
test.ts
、spec.ts
、e2e.ts
结尾的测试文件(适用于.js
、.jsx
和.tsx
文件) components
和component
目录utils
和util
目录- 不是
.js
、.jsx
、.ts
或.tsx
文件 - 文件内容不包含 JSX 元素
7 umi的路由
若配置文件(.umirc.ts 或 config/config.ts)中定义了 routes,则 禁用约定式路由,仅使用配置路由。
在配置文件中通过 routes
进行配置,格式为路由信息的数组。
// .umirc.ts export default { routes: [ { path: '/', component: 'index' }, { path: '/user', component: 'user' }, ], }
Umi 4 默认按页拆包,从而有更快的页面加载速度,由于加载过程是异步的,所以往往你需要编写 loading.tsx 来给项目添加加载样式,提升用户体验。
1.属性详解:
- path:
path
只支持两种占位符配置,第一种是动态参数:id
的形式,第二种是*
通配符,通配符只能出现路由字符串的最后。 - component:配置 location 和 path 匹配后用于渲染的 React 组件路径。可以是绝对路径,也可以是相对路径。如果是相对路径,会从
src/pages
开始寻找。如果指向src
目录的文件,可以用@
,比如component: '@/layouts/basic'
,推荐使用@
组织路由文件位置。 - routes:配置子路由,通常在需要为多个路径增加 layout 组件时使用。
//这样,访问 /list 和 /admin 就会带上 src/layouts/index 这个 layout 组件。 export default { routes: [ { path: '/login', component: 'login' }, { path: '/', component: '@/layouts/index', routes: [ { path: '/list', component: 'list' }, { path: '/admin', component: 'admin' }, ], }, ], }
在全局布局 src/layouts/index 中,通过 <Outlet/> 来渲染子路由
redirect:配置路由跳转。
//访问 / 会跳转到 /list 。 export default { routes: [ { path: '/', redirect: '/list' }, { path: '/list', component: 'list' }, ], }
重定向时,默认不会携带原 url 的查询参数,如需保持原参数,添加 keepQuery
选项即可:
routes: [ { path: '/', redirect: '/list', keepQuery: true }, // 注:若你需在跳转时处理参数,可以自行实现一个跳转组件 ]
- wrappers:配置路由组件的包装组件,通过包装组件可以为当前的路由组件组合进更多的功能。 比如,可以用于路由级别的权限校验:
export default { routes: [ { path: '/user', component: 'user', wrappers: [ '@/wrappers/auth', ], }, { path: '/login', component: 'login' }, ] }
然后在 src/wrappers/auth
中,
import { Navigate, Outlet } from 'umi' export default (props) => { const { isLogin } = useAuth(); if (isLogin) { return <Outlet />; } else{ return <Navigate to="/login" />; } }
这样,访问 /user,就通过 auth 组件做权限校验,如果通过,渲染 src/pages/user,否则跳转到 /login。
layout:通过配置 layout: false
可以单独关闭某一个路由的全局布局
layout: false 仅对一级路由生效
// .umirc.ts export default { routes: [ // 取消 login 页面的全局布局,从而自行实现整个页面 { path: '/login', component: '@/pages/Login', layout: false }, ], }
总结
到此这篇关于umi4.js基本使用方法的文章就介绍到这了,更多相关umi4.js详解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!