搭建基于umi框架的react项目
Umi 介绍
Umi,中文发音为「乌米」,是可扩展的企业级前端应用框架。Umi 以路由为基础,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。然后配以生命周期完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。
Umi 是蚂蚁集团的底层前端框架,已直接或间接地服务了 10000+ 应用,包括 Java、Node、H5 无线、离线(Hybrid)应用、纯前端 assets 应用、CMS 应用、Electron 应用、Serverless 应用等。他已经很好地服务了我们的内部用户,同时也服务了不少外部用户,包括淘系、飞猪、阿里云、字节、腾讯、口碑、美团等。在 2021 年字节的调研报告中,Umi 是其中 25.33% 开发者的选择。
Umi 有很多非常有意思的特性,比如。
- 企业级,在安全性、稳定性、最佳实践、约束能力方面会考虑更多
- 插件化,啥都能改,Umi 本身也是由插件构成
- MFSU,比 Vite 还快的 Webpack 打包方案
- 基于 React Router 6 的完备路由
- 默认最快的请求
- SSR & SSG
- 稳定白盒性能好的 ESLint 和 Jest
- React 18 的框架级接入
- Monorepo 最佳实践
创建项目
通过官方工具创建项目 -- umi 官网链接
pnpm dlx create-umi@latest // PNPM
npx create-umi@latest // NPM
yarn create umi // YARN
目录结构说明
├── config
│ └── config.ts # Umi 配置文件
├── src
│ ├── pages # 页面目录
│ │ └── index.tsx # 默认首页
│ ├── app.tsx # 运行时配置
│ └── global.css # 全局样式
├── package.json
└── .umirc.ts # Umi 主配置
核心配置
- 基础配置 [.umirc.ts]
import { defineConfig } from "umi";
export default defineConfig({
title: "Umi Project", // 项目标题
history: { type: "browser" }, // 路由模式:browser/hash
routes: [
{ path: "/", component: "index" },
{ path: "/users", component: "users" },
],
npmClient: "yarn", // 包管理器
publicPath: "/public/", // 静态资源路径
proxy: {
// 代理配置
"/api": {
target: "http://localhost:3000",
changeOrigin: true,
},
},
});
- 插件配置
安装常用插件:
yarn add @umijs/plugins
配置插件
export default {
plugins: [
"@umijs/plugins/dist/initial-state", // 初始化状态
"@umijs/plugins/dist/model", // 数据流
"@umijs/plugins/dist/locale", // 国际化
"@umijs/plugins/dist/antd", // Ant Design
"@umijs/plugins/dist/tailwindcss", // Tailwind CSS
"@umijs/plugins/dist/dva", // DVA 数据流
],
locale: { default: "zh-CN" }, // 默认语言
antd: { mobile: false }, // Ant Design 配置
};
路由
在 Umi 应用是单页应用,页面地址的跳转都是在浏览器端完成的,不会重新请求服务端获取 html,html 只在应用初始化时加载一次。所有页面由不同的组件构成,页面的切换其实就是不同组件的切换,你只需要在配置中把不同的路由路径和对应的组件关联上。
配置路由
在配置文件中通过 routes 进行配置,格式为路由信息的数组。
// .umirc.ts
export default {
routes: [
{ path: "/", component: "index" },
{ path: "/user", component: "user" },
],
};
path
- Type: string
path 只支持两种占位符配置,第一种是动态参数 :id 的形式,第二种是 * 通配符,通配符只能出现路由字符串的最后。
✅ 以下是目前支持的路由路径配置形式:
/groups
/groups/admin
/users/:id
/users/:id/messages
/files/*
/files/:id/*
❌ 以下是目前不支持的路由路径配置形式:
/users/:id?
/tweets/:id(\d+)
/files/*/cat.jpg
/files-*
component
- Type: string
配置location和path匹配后用于渲染的 React组件路径。可以是绝对路径,也可以是相对路径。如果是相对路径,会从src/pages开始寻找。
如果指向src目录的文件,可以用@,比如 component: '@/layouts/basic',推荐使用@组织路由文件位置。
Dva 状态管理
如下图所示,Umi 内置了 Dva 提供了一套状态管理方案:

代码示意
import axios from "axios";
import { Effect, Reducer } from "umi";
const STATE = { list: [] as ItemType[] };
interface DocType<T = typeof STATE> {
namespace: "docs";
state: T;
reducers: { setList: Reducer<T> };
effects: { getDate: Effect };
}
export interface ItemType {
userId: number;
id: number;
title: string;
body: string;
}
export default const docs: DocType = {
namespace: "docs",
state: STATE,
// 同步修改数据
reducers: {
setList(_, { payload }) {
return { list: payload.data };
},
},
// 异步请求接口
effects: {
*getDate(_, { call, put }) {
try {
const = "http://jsonplaceholder.typicode.com/posts"
const { data } = yield call(() => axios.get(url));
yield put({ type: "setList", payload: { data } });
} catch (error) {
console.log(error, "docs--error");
}
},
},
};
在Class组件使用
import React from "react";
import { connect, Dispatch } from "umi";
import { ItemType } from "../models/docs";
// 定义 Props 类型
interface DocsProps {
list: ItemType[];
dispatch: Dispatch;
}
class Docs extends React.Component<DocsProps> {
constructor(props: DocsProps) {
super(props);
}
componentDidMount() {
this.props.dispatch({ type: "docs/getDate" }); // 调用接口
}
render() {
return (
<div>
<h1>这是Docs 页面</h1>
<div>
{this.props.list.map(item => (
<div key={item.id}>{item.title}</div>
))}
</div>
</div>
);
}
}
// connect来联系store
export default connect((store: { docs: { list: ItemType[] } }) => ({
list: store.docs.list,
}))(Docs);