轩辕李的博客 轩辕李的博客
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • JavaScript
  • TypeScript
  • Node.js
  • 前端框架
  • 前端工程化
  • 浏览器与Web API
  • 架构设计与模式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

轩辕李

勇猛精进,星辰大海
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • JavaScript
  • TypeScript
  • Node.js
  • 前端框架
  • 前端工程化
  • 浏览器与Web API
  • 架构设计与模式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • JavaScript

  • TypeScript

  • Node.js

  • 前端框架

    • Vue.js快速入门
    • Vue.js历代版本新特性
    • Nuxt.js极简入门
    • React极简入门
    • UmiJS快速入门
      • 一、UmiJS 简介
        • 什么是 UmiJS
        • 核心特性
        • 为什么选择 UmiJS
        • 适用场景
      • 二、环境准备
        • 开发环境要求
        • 验证环境
        • 创建第一个 Umi 项目
        • 项目结构
      • 三、核心概念
        • 1. 约定式路由
        • 基础路由
        • 创建第一个页面
        • 动态路由
        • 嵌套路由
        • 2. 路由配置
        • 3. 导航
        • 使用 Link 组件
        • 使用 history API
        • 4. 布局
        • 5. 请求数据
        • 配置 request
        • 创建 API 服务
        • 在组件中使用
        • 6. Mock 数据
        • 7. 状态管理
        • 创建 Model
        • 在组件中使用
      • 四、实战示例:用户管理系统
        • 1. 项目结构
        • 2. 用户列表页面
        • 3. 创建用户页面
      • 五、常用配置
        • 1. 基础配置
        • 2. 插件配置
        • 3. 环境变量
      • 六、最佳实践
        • 1. 目录组织
        • 2. 代码分割
        • 3. 权限控制
        • 4. 错误处理
      • 七、集成 Ant Design
        • 1. 安装
        • 2. 使用组件
      • 八、构建和部署
        • 1. 构建
        • 2. 本地预览
        • 3. 部署
        • 部署到 Nginx
        • 部署到 CDN
      • 九、学习资源
        • 官方文档
        • 推荐阅读
        • 进阶主题
      • 十、总结
  • 工程化

  • 浏览器与Web API

  • 前端
  • 前端框架
轩辕李
2025-01-15
目录

UmiJS快速入门

本文面向具有 React 基础的开发者,快速介绍 UmiJS 4.x 的核心概念和开发方式。如果你已经熟悉 React 和基本的前端开发,这篇文章将帮助你快速上手 Umi。

# 一、UmiJS 简介

# 什么是 UmiJS

UmiJS(简称 Umi)是蚂蚁集团开源的企业级前端开发框架。它基于 React,提供开箱即用的开发体验,内置路由、构建、部署、测试等功能。

UmiJS 与 React 的关系:

  • React 是 UI 库,专注于视图层
  • UmiJS 是基于 React 的应用框架,提供完整的工程化解决方案
  • 如果你还不熟悉 React,建议先阅读 React极简入门

# 核心特性

  1. 开箱即用:零配置即可开发,内置路由、构建、部署等功能
  2. 约定式路由:基于文件系统的路由,自动生成路由配置
  3. 插件化:强大的插件体系,易于扩展
  4. TypeScript 支持:原生支持 TypeScript
  5. 企业级:经过蚂蚁集团大规模业务验证
  6. 性能优化:内置 MFSU、预渲染等优化方案

# 为什么选择 UmiJS

特性 UmiJS Create React App Next.js
路由方案 约定式 + 配置式 需自行安装 文件系统路由
服务端渲染 支持(MFSU) 不支持 支持(主要特性)
插件体系 强大 基础 适中
企业级场景 ✅ ❌ ✅
学习曲线 适中 简单 适中
中文文档 完善 一般 较好

# 适用场景

  • 中后台系统:后台管理系统、数据大屏等
  • 企业级应用:需要完整工程化方案的项目
  • 多页应用:支持 MPA 模式
  • 移动端 H5:配合 Ant Design Mobile
  • 微前端:内置 qiankun 微前端方案

# 二、环境准备

# 开发环境要求

  • Node.js 14 或更高版本(推荐 18.x)
  • 包管理器:npm、yarn 或 pnpm
  • 代码编辑器:推荐 VS Code

# 验证环境

node -v  # 应该 >= 14.0.0
npm -v

# 创建第一个 Umi 项目

使用官方脚手架创建项目:

# 使用 pnpm(推荐)
pnpm create umi

# 或使用 npm
npx create-umi@latest

创建完成后:

cd my-umi-app
pnpm install
pnpm dev

浏览器访问 http://localhost:8000,看到欢迎页面表示成功。

# 项目结构

my-umi-app/
├── .umirc.ts              # Umi 配置文件
├── package.json
├── tsconfig.json
├── src/
│   ├── .umi/             # Umi 临时文件(自动生成,不要修改)
│   ├── layouts/          # 全局布局
│   │   └── index.tsx
│   ├── pages/            # 页面目录(约定式路由)
│   │   ├── index.tsx     # 首页 -> /
│   │   └── users/
│   │       └── index.tsx # 用户页 -> /users
│   ├── models/           # 全局数据流(dva)
│   ├── services/         # 接口请求
│   ├── components/       # 业务组件
│   └── app.ts            # 运行时配置
└── mock/                 # Mock 数据

# 三、核心概念

# 1. 约定式路由

Umi 会自动根据 pages 目录结构生成路由。

# 基础路由

src/pages/
├── index.tsx          -> /
├── users.tsx          -> /users
├── users/
│   ├── index.tsx      -> /users
│   └── profile.tsx    -> /users/profile
└── about.tsx          -> /about

# 创建第一个页面

创建 src/pages/users/index.tsx:

import React from 'react';

export default function UsersPage() {
  return (
    <div>
      <h1>用户列表</h1>
      <ul>
        <li>张三</li>
        <li>李四</li>
        <li>王五</li>
      </ul>
    </div>
  );
}

访问 http://localhost:8000/users 即可看到页面。

# 动态路由

使用 [id] 表示动态参数:

src/pages/
└── users/
    └── [id].tsx       -> /users/1, /users/2, ...

src/pages/users/[id].tsx:

import { useParams } from 'umi';

export default function UserDetailPage() {
  const params = useParams<{ id: string }>();

  return (
    <div>
      <h1>用户详情</h1>
      <p>用户 ID:{params.id}</p>
    </div>
  );
}

访问 http://localhost:8000/users/123,页面显示"用户 ID:123"。

# 嵌套路由

创建嵌套路由需要在父组件中使用 <Outlet />:

src/pages/users.tsx:

import { Outlet, Link } from 'umi';

export default function UsersLayout() {
  return (
    <div>
      <h1>用户管理</h1>
      <nav>
        <Link to="/users">用户列表</Link> | 
        <Link to="/users/create">创建用户</Link>
      </nav>
      <hr />
      <Outlet />  {/* 子路由渲染位置 */}
    </div>
  );
}

src/pages/users/index.tsx:

export default function UsersList() {
  return <div>用户列表页面</div>;
}

src/pages/users/create.tsx:

export default function UsersCreate() {
  return <div>创建用户页面</div>;
}

# 2. 路由配置

除了约定式路由,也支持配置式路由。在 .umirc.ts 中配置:

import { defineConfig } from 'umi';

export default defineConfig({
  routes: [
    { path: '/', component: '@/pages/index' },
    { 
      path: '/users', 
      component: '@/pages/users',
      routes: [
        { path: '/users', component: '@/pages/users/index' },
        { path: '/users/:id', component: '@/pages/users/[id]' },
      ]
    },
  ],
});

# 3. 导航

使用 Link 组件或 history API 进行导航。

# 使用 Link 组件

import { Link } from 'umi';

export default function HomePage() {
  return (
    <div>
      <h1>首页</h1>
      {/* 声明式导航 */}
      <Link to="/users">查看用户</Link>
      <Link to="/users/123">查看用户 123</Link>
    </div>
  );
}

# 使用 history API

import { history } from 'umi';

export default function LoginPage() {
  const handleLogin = () => {
    // 模拟登录
    console.log('登录成功');
    
    // 编程式导航
    history.push('/dashboard');
    
    // 或使用 replace(不会产生历史记录)
    // history.replace('/dashboard');
  };

  return (
    <div>
      <h1>登录</h1>
      <button onClick={handleLogin}>登录</button>
    </div>
  );
};

# 4. 布局

创建全局布局 src/layouts/index.tsx:

import { Link, Outlet } from 'umi';
import './index.less';

export default function Layout() {
  return (
    <div className="layout">
      <header className="header">
        <div className="logo">我的应用</div>
        <nav>
          <Link to="/">首页</Link>
          <Link to="/users">用户</Link>
          <Link to="/about">关于</Link>
        </nav>
      </header>
      
      <main className="content">
        <Outlet />  {/* 页面内容渲染位置 */}
      </main>
      
      <footer className="footer">
        © 2024 我的应用
      </footer>
    </div>
  );
}

样式文件 src/layouts/index.less:

.layout {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 20px;
  background: #001529;
  color: white;
  height: 64px;

  .logo {
    font-size: 20px;
    font-weight: bold;
  }

  nav {
    a {
      color: rgba(255, 255, 255, 0.65);
      margin-left: 20px;
      text-decoration: none;

      &:hover {
        color: white;
      }
    }
  }
}

.content {
  flex: 1;
  padding: 20px;
}

.footer {
  text-align: center;
  padding: 20px;
  background: #f0f2f5;
}

# 5. 请求数据

Umi 推荐使用内置的 request 进行数据请求。

# 配置 request

在 src/app.ts 中配置全局请求设置:

import { RequestConfig } from 'umi';

export const request: RequestConfig = {
  timeout: 10000,
  errorConfig: {
    adaptor: (resData) => {
      return {
        ...resData,
        success: resData.code === 0,
        errorMessage: resData.message,
      };
    },
  },
  requestInterceptors: [
    (url, options) => {
      // 添加 token
      const token = localStorage.getItem('token');
      return {
        url,
        options: {
          ...options,
          headers: {
            ...options.headers,
            Authorization: token ? `Bearer ${token}` : '',
          },
        },
      };
    },
  ],
  responseInterceptors: [
    (response) => {
      // 统一错误处理
      return response;
    },
  ],
};

# 创建 API 服务

src/services/user.ts:

import { request } from 'umi';

export interface User {
  id: number;
  name: string;
  email: string;
  age: number;
}

// 获取用户列表
export async function getUsers() {
  return request<{ data: User[] }>('/api/users', {
    method: 'GET',
  });
}

// 获取用户详情
export async function getUser(id: number) {
  return request<{ data: User }>(`/api/users/${id}`, {
    method: 'GET',
  });
}

// 创建用户
export async function createUser(data: Partial<User>) {
  return request<{ data: User }>('/api/users', {
    method: 'POST',
    data,
  });
}

// 更新用户
export async function updateUser(id: number, data: Partial<User>) {
  return request<{ data: User }>(`/api/users/${id}`, {
    method: 'PUT',
    data,
  });
}

// 删除用户
export async function deleteUser(id: number) {
  return request(`/api/users/${id}`, {
    method: 'DELETE',
  });
}

# 在组件中使用

import React, { useState, useEffect } from 'react';
import { getUsers, User } from '@/services/user';

export default function UsersPage() {
  const [users, setUsers] = useState<User[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchUsers();
  }, []);

  const fetchUsers = async () => {
    try {
      setLoading(true);
      const response = await getUsers();
      setUsers(response.data);
    } catch (error) {
      console.error('获取用户列表失败', error);
    } finally {
      setLoading(false);
    }
  };

  if (loading) {
    return <div>加载中...</div>;
  }

  return (
    <div>
      <h1>用户列表</h1>
      <ul>
        {users.map(user => (
          <li key={user.id}>
            {user.name} - {user.email}
          </li>
        ))}
      </ul>
    </div>
  );
}

# 6. Mock 数据

开发时可以使用 Mock 数据。创建 mock/users.ts:

import { defineMock } from 'umi';

export default defineMock({
  // 获取用户列表
  'GET /api/users': (req, res) => {
    res.json({
      code: 0,
      message: 'success',
      data: [
        { id: 1, name: '张三', email: 'zhangsan@example.com', age: 28 },
        { id: 2, name: '李四', email: 'lisi@example.com', age: 32 },
        { id: 3, name: '王五', email: 'wangwu@example.com', age: 25 },
      ],
    });
  },

  // 获取用户详情
  'GET /api/users/:id': (req, res) => {
    const { id } = req.params;
    res.json({
      code: 0,
      message: 'success',
      data: {
        id: Number(id),
        name: `用户${id}`,
        email: `user${id}@example.com`,
        age: 20 + Number(id),
      },
    });
  },

  // 创建用户
  'POST /api/users': (req, res) => {
    res.json({
      code: 0,
      message: 'success',
      data: {
        id: Math.floor(Math.random() * 1000),
        ...req.body,
      },
    });
  },

  // 更新用户
  'PUT /api/users/:id': (req, res) => {
    res.json({
      code: 0,
      message: 'success',
      data: {
        id: Number(req.params.id),
        ...req.body,
      },
    });
  },

  // 删除用户
  'DELETE /api/users/:id': (req, res) => {
    res.json({
      code: 0,
      message: 'success',
    });
  },
});

# 7. 状态管理

Umi 内置了简化版的 dva,支持全局状态管理。

# 创建 Model

src/models/user.ts:

import { useState } from 'react';
import { getUsers, User } from '@/services/user';

export default function useUserModel() {
  const [users, setUsers] = useState<User[]>([]);
  const [loading, setLoading] = useState(false);

  const fetchUsers = async () => {
    setLoading(true);
    try {
      const response = await getUsers();
      setUsers(response.data);
    } catch (error) {
      console.error('获取用户失败', error);
    } finally {
      setLoading(false);
    }
  };

  const addUser = (user: User) => {
    setUsers([...users, user]);
  };

  const removeUser = (id: number) => {
    setUsers(users.filter(u => u.id !== id));
  };

  return {
    users,
    loading,
    fetchUsers,
    addUser,
    removeUser,
  };
}

# 在组件中使用

import { useModel } from 'umi';
import { useEffect } from 'react';

export default function UsersPage() {
  const { users, loading, fetchUsers, removeUser } = useModel('user');

  useEffect(() => {
    fetchUsers();
  }, []);

  const handleDelete = (id: number) => {
    if (confirm('确定删除吗?')) {
      removeUser(id);
    }
  };

  if (loading) {
    return <div>加载中...</div>;
  }

  return (
    <div>
      <h1>用户列表</h1>
      <table>
        <thead>
          <tr>
            <th>ID</th>
            <th>姓名</th>
            <th>邮箱</th>
            <th>年龄</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          {users.map(user => (
            <tr key={user.id}>
              <td>{user.id}</td>
              <td>{user.name}</td>
              <td>{user.email}</td>
              <td>{user.age}</td>
              <td>
                <button onClick={() => handleDelete(user.id)}>删除</button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

# 四、实战示例:用户管理系统

# 1. 项目结构

src/
├── layouts/
│   └── index.tsx        # 全局布局
├── pages/
│   ├── index.tsx        # 首页
│   └── users/
│       ├── index.tsx    # 用户列表
│       ├── create.tsx   # 创建用户
│       └── [id].tsx     # 用户详情
├── models/
│   └── user.ts          # 用户 Model
├── services/
│   └── user.ts          # 用户 API
└── components/
    └── UserForm.tsx     # 用户表单组件

# 2. 用户列表页面

src/pages/users/index.tsx:

import { useModel, history } from 'umi';
import { useEffect } from 'react';
import './index.less';

export default function UsersPage() {
  const { users, loading, fetchUsers, removeUser } = useModel('user');

  useEffect(() => {
    fetchUsers();
  }, []);

  const handleDelete = async (id: number) => {
    if (confirm('确定删除吗?')) {
      removeUser(id);
    }
  };

  const handleEdit = (id: number) => {
    history.push(`/users/${id}`);
  };

  if (loading) {
    return <div className="loading">加载中...</div>;
  }

  return (
    <div className="users-page">
      <div className="header">
        <h1>用户管理</h1>
        <button 
          className="btn-primary"
          onClick={() => history.push('/users/create')}
        >
          创建用户
        </button>
      </div>

      <table className="users-table">
        <thead>
          <tr>
            <th>ID</th>
            <th>姓名</th>
            <th>邮箱</th>
            <th>年龄</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          {users.map(user => (
            <tr key={user.id}>
              <td>{user.id}</td>
              <td>{user.name}</td>
              <td>{user.email}</td>
              <td>{user.age}</td>
              <td>
                <button 
                  className="btn-link"
                  onClick={() => handleEdit(user.id)}
                >
                  编辑
                </button>
                <button 
                  className="btn-link btn-danger"
                  onClick={() => handleDelete(user.id)}
                >
                  删除
                </button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>

      {users.length === 0 && (
        <div className="empty">暂无数据</div>
      )}
    </div>
  );
}

样式 src/pages/users/index.less:

.users-page {
  .header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;

    h1 {
      margin: 0;
    }
  }

  .users-table {
    width: 100%;
    border-collapse: collapse;

    th, td {
      padding: 12px;
      text-align: left;
      border-bottom: 1px solid #e8e8e8;
    }

    th {
      background: #fafafa;
      font-weight: 600;
    }

    tbody tr:hover {
      background: #fafafa;
    }
  }

  .btn-primary {
    padding: 8px 16px;
    background: #1890ff;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;

    &:hover {
      background: #40a9ff;
    }
  }

  .btn-link {
    padding: 4px 8px;
    margin-right: 8px;
    background: transparent;
    color: #1890ff;
    border: none;
    cursor: pointer;

    &:hover {
      color: #40a9ff;
    }

    &.btn-danger {
      color: #ff4d4f;

      &:hover {
        color: #ff7875;
      }
    }
  }

  .loading, .empty {
    text-align: center;
    padding: 40px;
    color: #999;
  }
}

# 3. 创建用户页面

src/pages/users/create.tsx:

import { useState } from 'react';
import { history, useModel } from 'umi';
import { createUser } from '@/services/user';
import './form.less';

export default function CreateUserPage() {
  const { addUser } = useModel('user');
  const [loading, setLoading] = useState(false);
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    age: 0,
  });

  const handleChange = (field: string, value: any) => {
    setFormData({ ...formData, [field]: value });
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    
    if (!formData.name || !formData.email) {
      alert('请填写完整信息');
      return;
    }

    try {
      setLoading(true);
      const response = await createUser(formData);
      addUser(response.data);
      alert('创建成功');
      history.push('/users');
    } catch (error) {
      alert('创建失败');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="user-form-page">
      <h1>创建用户</h1>
      
      <form onSubmit={handleSubmit} className="user-form">
        <div className="form-item">
          <label>姓名:</label>
          <input
            type="text"
            value={formData.name}
            onChange={(e) => handleChange('name', e.target.value)}
            placeholder="请输入姓名"
          />
        </div>

        <div className="form-item">
          <label>邮箱:</label>
          <input
            type="email"
            value={formData.email}
            onChange={(e) => handleChange('email', e.target.value)}
            placeholder="请输入邮箱"
          />
        </div>

        <div className="form-item">
          <label>年龄:</label>
          <input
            type="number"
            value={formData.age}
            onChange={(e) => handleChange('age', Number(e.target.value))}
            placeholder="请输入年龄"
          />
        </div>

        <div className="form-actions">
          <button type="submit" disabled={loading}>
            {loading ? '提交中...' : '提交'}
          </button>
          <button type="button" onClick={() => history.back()}>
            取消
          </button>
        </div>
      </form>
    </div>
  );
}

样式 src/pages/users/form.less:

.user-form-page {
  max-width: 600px;

  h1 {
    margin-bottom: 24px;
  }

  .user-form {
    .form-item {
      margin-bottom: 20px;

      label {
        display: block;
        margin-bottom: 8px;
        font-weight: 500;
      }

      input {
        width: 100%;
        padding: 8px 12px;
        border: 1px solid #d9d9d9;
        border-radius: 4px;
        font-size: 14px;

        &:focus {
          outline: none;
          border-color: #1890ff;
        }
      }
    }

    .form-actions {
      margin-top: 24px;
      display: flex;
      gap: 12px;

      button {
        padding: 8px 24px;
        border: none;
        border-radius: 4px;
        cursor: pointer;
        font-size: 14px;

        &[type="submit"] {
          background: #1890ff;
          color: white;

          &:hover:not(:disabled) {
            background: #40a9ff;
          }

          &:disabled {
            opacity: 0.5;
            cursor: not-allowed;
          }
        }

        &[type="button"] {
          background: #f0f0f0;
          color: #333;

          &:hover {
            background: #e0e0e0;
          }
        }
      }
    }
  }
}

# 五、常用配置

# 1. 基础配置

.umirc.ts:

import { defineConfig } from 'umi';

export default defineConfig({
  // 标题
  title: '我的应用',
  
  // 部署路径
  base: '/',
  publicPath: '/',
  
  // 输出目录
  outputPath: 'dist',
  
  // 代理配置
  proxy: {
    '/api': {
      target: 'http://localhost:3000',
      changeOrigin: true,
    },
  },
  
  // 路由模式
  history: { type: 'hash' }, // 或 'browser'
  
  // 开启 hash 文件名
  hash: true,
  
  // 压缩代码
  jsMinifier: 'esbuild',
  cssMinifier: 'esbuild',
});

# 2. 插件配置

export default defineConfig({
  plugins: [
    '@umijs/plugins/dist/initial-state',
    '@umijs/plugins/dist/model',
    '@umijs/plugins/dist/request',
  ],
  
  // Ant Design 配置
  antd: {},
  
  // 初始化数据
  initialState: {},
  
  // Model 插件配置
  model: {},
});

# 3. 环境变量

创建 .env 文件:

# 开发环境
UMI_ENV=dev
API_URL=http://localhost:3000

创建 .env.production:

# 生产环境
UMI_ENV=prod
API_URL=https://api.example.com

在代码中使用:

const apiUrl = process.env.API_URL;

# 六、最佳实践

# 1. 目录组织

src/
├── components/          # 通用组件
│   ├── Button/
│   ├── Card/
│   └── Table/
├── pages/              # 页面
│   ├── users/
│   └── dashboard/
├── models/             # 数据模型
├── services/           # API 服务
├── utils/              # 工具函数
│   ├── request.ts
│   └── format.ts
├── constants/          # 常量
│   └── index.ts
└── types/              # TypeScript 类型
    └── user.ts

# 2. 代码分割

使用动态导入实现按需加载:

import { lazy } from 'react';

const UsersPage = lazy(() => import('./pages/users'));

# 3. 权限控制

在 src/app.tsx 中配置:

import { RunTimeLayoutConfig } from 'umi';

export const layout: RunTimeLayoutConfig = () => {
  return {
    // 权限配置
    rightRender: () => <div>用户信息</div>,
    onPageChange: () => {
      // 页面切换时检查权限
      const token = localStorage.getItem('token');
      if (!token && location.pathname !== '/login') {
        history.push('/login');
      }
    },
  };
};

# 4. 错误处理

创建全局错误边界:

import React from 'react';

export default class ErrorBoundary extends React.Component {
  state = { hasError: false };

  static getDerivedStateFromError(error: any) {
    return { hasError: true };
  }

  componentDidCatch(error: any, errorInfo: any) {
    console.error('错误:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <div>出错了!</div>;
    }

    return this.props.children;
  }
}

# 七、集成 Ant Design

# 1. 安装

Umi 4 已内置 Ant Design 5,开启即可:

.umirc.ts:

export default defineConfig({
  antd: {},
});

# 2. 使用组件

import { Button, Table, Form, Input, message } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { User } from '@/services/user';

export default function UsersPage() {
  const columns: ColumnsType<User> = [
    {
      title: 'ID',
      dataIndex: 'id',
      key: 'id',
    },
    {
      title: '姓名',
      dataIndex: 'name',
      key: 'name',
    },
    {
      title: '邮箱',
      dataIndex: 'email',
      key: 'email',
    },
    {
      title: '年龄',
      dataIndex: 'age',
      key: 'age',
    },
    {
      title: '操作',
      key: 'action',
      render: (_, record) => (
        <Button type="link" onClick={() => handleEdit(record.id)}>
          编辑
        </Button>
      ),
    },
  ];

  const handleEdit = (id: number) => {
    message.success('编辑用户:' + id);
  };

  return (
    <div>
      <Table columns={columns} dataSource={[]} rowKey="id" />
    </div>
  );
}

# 八、构建和部署

# 1. 构建

# 生产环境构建
pnpm build

# 指定环境构建
UMI_ENV=test pnpm build

构建后的文件在 dist 目录。

# 2. 本地预览

pnpm preview

# 3. 部署

# 部署到 Nginx

server {
  listen 80;
  server_name example.com;
  root /var/www/dist;
  index index.html;

  location / {
    try_files $uri $uri/ /index.html;
  }
}

# 部署到 CDN

在 .umirc.ts 中配置:

export default defineConfig({
  publicPath: 'https://cdn.example.com/',
});

# 九、学习资源

# 官方文档

  • UmiJS 官方文档 (opens new window)
  • Ant Design 官方文档 (opens new window)

# 推荐阅读

  • Ant Design Pro:基于 Umi + Ant Design 的企业级中后台解决方案
  • dumi:基于 Umi 的组件文档工具
  • qiankun:Umi 内置的微前端方案

# 进阶主题

  • 微前端架构
  • 性能优化(MFSU)
  • 服务端渲染(SSR)
  • 自定义插件开发
  • 国际化(i18n)
  • 主题定制

# 十、总结

UmiJS 的核心特性:

  1. 约定式路由:基于文件系统自动生成路由
  2. 开箱即用:内置构建、部署、测试等功能
  3. 插件化:强大的插件体系
  4. 企业级:经过大规模业务验证

开始使用 UmiJS 的步骤:

  1. 创建项目:pnpm create umi
  2. 熟悉约定式路由
  3. 掌握数据请求和状态管理
  4. 集成 Ant Design
  5. 实践完整项目

UmiJS 特别适合构建中后台系统和企业级应用,它的约定式路由和插件化设计能够大幅提升开发效率!

祝你变得更强!

编辑 (opens new window)
#UmiJS#React#前端框架
上次更新: 2025/12/25
React极简入门
Vite极简入门

← React极简入门 Vite极简入门→

最近更新
01
AI编程时代的一些心得
09-11
02
Claude Code 最佳实践(个人版)
08-01
03
高扩展-弹性伸缩设计
06-05
更多文章>
Theme by Vdoing | Copyright © 2018-2025 京ICP备2021021832号-2 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式