搭建基于umi框架的react项目

Umi 介绍

Umi,中文发音为「乌米」,是可扩展的企业级前端应用框架。Umi 以路由为基础,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。然后配以生命周期完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。

Umi 是蚂蚁集团的底层前端框架,已直接或间接地服务了 10000+ 应用,包括 Java、Node、H5 无线、离线(Hybrid)应用、纯前端 assets 应用、CMS 应用、Electron 应用、Serverless 应用等。他已经很好地服务了我们的内部用户,同时也服务了不少外部用户,包括淘系、飞猪、阿里云、字节、腾讯、口碑、美团等。在 2021 年字节的调研报告中,Umi 是其中 25.33% 开发者的选择。

Umi 有很多非常有意思的特性,比如。

  1. 企业级,在安全性、稳定性、最佳实践、约束能力方面会考虑更多
  2. 插件化,啥都能改,Umi 本身也是由插件构成
  3. MFSU,比 Vite 还快的 Webpack 打包方案
  4. 基于 React Router 6 的完备路由
  5. 默认最快的请求
  6. SSR & SSG
  7. 稳定白盒性能好的 ESLint 和 Jest
  8. React 18 的框架级接入
  9. Monorepo 最佳实践

创建项目

通过官方工具创建项目 -- umi 官网链接open in new window

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 主配置

核心配置

  1. 基础配置 [.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,
		},
	},
});
  1. 插件配置

安装常用插件:

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

配置locationpath匹配后用于渲染的 React组件路径。可以是绝对路径,也可以是相对路径。如果是相对路径,会从src/pages开始寻找。

如果指向src目录的文件,可以用@,比如 component: '@/layouts/basic',推荐使用@组织路由文件位置。

Dva 状态管理

如下图所示,Umi 内置了 Dva 提供了一套状态管理方案:

alt text

代码示意

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);
上次更新 2025/3/19 16:57:59