# 一、Umi简介
一个可插拔的企业级
react应用框架。umi以路由为基础的,以及各种进阶的路由功能,并以此进行功能扩展,比如支持路由级的按需加载。然后配以完善的插件体系,覆盖从源码到构建产物的每个生命周期
# 1.1 特性
- 开箱即用,内置
react、react-router等 - 支持配置的路由方式
- 完善的插件体系,覆盖从源码到构建产物的每个生命周期
- 高性能,通过插件支持
PWA、以路由为单元的code splitting等 - 支持静态页面导出,适配各种环境,比如中台业务、无线业务、egg、支付宝钱包、云凤蝶等
- 开发启动快,支持一键开启
dll和hard-source-webpack-plugin等 - 一键兼容到
IE9,基于umi-plugin-polyfills - 完善的
TypeScript支持,包括d.ts定义和umi test - 与
dva数据流的深入融合,支持duck directory、model的自动加载、code splitting等等
# 1.2 架构

# 1.3 和 dva、roadhog关系
roadhog是基于webpack的封装工具,目的是简化webpack的配置 umi 可以简单地理解为roadhog + 路由,思路类似next.js/nuxt.js,辅以一套插件机制,目的是通过框架的方式简化React开发dva目前是纯粹的数据流,和umi以及roadhog之间并没有相互的依赖关系,可以分开使用也可以一起使用
# 二、环境搭建
$ mkdir myapp && cd myapp
$ yarn create umi

确定后,会根据你的选择自动创建好目录和文件

# 三、目录结构
dva项目之前通常都是这种扁平的组织方式
+ models
- global.js
- a1.js
- a2.js
- b.js
+ services
- a.js
- b.js
+ routes
- PageA.js
- PageB.js
用了
umi后,可以按页面维度进行组织
+ models/global.js
+ pages
+ a
- index.js
+ models
- a1.js
- a2.js
+ services
- a.js
+ b
- index.js
- model.js
- service.js
好处是更加结构更加清晰了,减少耦合,一删全删,方便 copy 和共享
自动注册 models
+ src
+ models
- g.js
+ pages
+ a
+ models
- a.js
- b.js
+ ss
- s.js
- page.js
+ c
- model.js
+ d
+ models
- d.js
- page.js
- page.js
global model为src/models/g.js/a的page model为src/pages/a/models/{a,b,ss/s}.js/c的page model为src/pages/c/model.js/c/d的page model为src/pages/c/model.js,src/pages/c/d/models/d.js
一个复杂应用的目录结构如下
.
├── dist/ // 默认的 build 输出目录
├── mock/ // mock 文件所在目录,基于 express
├── config/
├── config.js // umi 配置,同 .umirc.js,二选一
└── src/ // 源码目录,可选
├── layouts/index.js // 全局布局
├── pages/ // 页面目录,里面的文件即路由
├── .umi/ // dev 临时目录,需添加到 .gitignore
├── .umi-production/ // build 临时目录,会自动删除
├── document.ejs // HTML 模板
├── 404.js // 404 页面
├── page1.js // 页面 1,任意命名,导出 react 组件
├── page1.test.js // 用例文件,umi test 会匹配所有 .test.js 和 .e2e.js 结尾的文件
└── page2.js // 页面 2,任意命名
├── global.css // 约定的全局样式文件,自动引入,也可以用 global.less
├── global.js // 可以在这里加入 polyfill
├── .umirc.js // umi 配置,同 config/config.js,二选一
├── .env // 环境变量
└── package.json
1、dist
默认输出路径,可通过配置
outputPath修改
2、mock
约定
mock目录里所有的.js文件会被解析为mock文件
比如,新建 mock/users.js,内容如下:
export default {
'/api/users': ['a', 'b'],
}
然后在浏览器里访问
http://localhost:8000/api/users 就可以看到 ['a', 'b']了
3、src
约定 src 为源码目录,但是可选,简单项目可以不加 src 这层目录
比如:下面两种目录结构的效果是一致的。
+ src
+ pages
- index.js
+ layouts
- index.js
- .umirc.js
+ pages
- index.js
+ layouts
- index.js
- .umirc.js
4、src/layouts/index.js
全局布局,实际上是在路由外面套了一层
比如,你的路由是:
[
{ path: '/', component: './pages/index' },
{ path: '/users', component: './pages/users' },
]
如果有 layouts/index.js,那么路由则变为:
[
{ path: '/', component: './layouts/index', routes: [
{ path: '/', component: './pages/index' },
{ path: '/users', component: './pages/users' },
] }
]
5、src/pages
约定
pages下所有的(j|t)sx?文件即路由
6、src/pages/404.js
404页面。注意开发模式下有内置 umi 提供的 404 提示页面,所以只有显式访问/404才能访问到这个页面
7、src/pages/document.ejs
有这个文件时,会覆盖默认的 HTML 模板。需至少包含以下代码,
<div id="root"></div>
8、src/pages/.umi
这是
umi dev时生产的临时目录,默认包含umi.js和router.js,有些插件也会在这里生成一些其他临时文件。可以在这里做一些验证,但请不要直接在这里修改代码,umi重启或者pages下的文件修改都会重新生成这个文件夹下的文件
9、src/pages/.umi-production
同
src/pagers/.umi,但是是在umi build时生成的,会在umi build执行完自动删除
10、src/global.(j|t)sx?
在入口文件最前面被自动引入,可以考虑在此加入
polyfill
11、src/global.(css|less|sass|scss)
这个文件不走
css modules,自动被引入,可以写一些全局样式,或者做一些样式覆盖
12、.umirc.js 和 config/config.js
umi的配置文件,二选一
13、.env
环境变量,比如:
CLEAR_CONSOLE=none
BROWSER=none
# 四、路由配置
# 4.1 约定式路由
# 4.1.1 基础路由
假设 pages 目录结构如下:
+ pages/
+ users/
- index.js
- list.js
- index.js
那么,umi 会自动生成路由配置如下:
[
{ path: '/', component: './pages/index.js' },
{ path: '/users/', component: './pages/users/index.js' },
{ path: '/users/list', component: './pages/users/list.js' },
]
# 4.1.2 动态路由
umi里约定,带$前缀的目录或文件为动态路由。
比如以下目录结构:
+ pages/
+ $post/
- index.js
- comments.js
+ users/
$id.js
- index.js
会生成路由配置如下:
[
{ path: '/', component: './pages/index.js' },
{ path: '/users/:id', component: './pages/users/$id.js' },
{ path: '/:post/', component: './pages/$post/index.js' },
{ path: '/:post/comments', component: './pages/$post/comments.js' },
]
# 4.1.3 可选的动态路由
umi里约定动态路由如果带$后缀,则为可选动态路由。
比如以下结构:
+ pages/
+ users/
- $id$.js
- index.js
会生成路由配置如下:
[
{ path: '/': component: './pages/index.js' },
{ path: '/users/:id?': component: './pages/users/$id$.js' },
]
# 4.1.4 嵌套路由
umi里约定目录下有_layout.js时会生成嵌套路由,以_layout.js为该目录的layout。
比如以下目录结构:
+ pages/
+ users/
- _layout.js
- $id.js
- index.js
会生成路由配置如下:
[
{ path: '/users': component: './pages/users/_layout.js'
routes: [
{ path: '/users/', component: './pages/users/index.js' },
{ path: '/users/:id', component: './pages/users/$id.js' },
],
},
]
# 4.1.5 全局 layout
约定
src/layouts/index.js为全局路由,返回一个 React 组件,通过props.children渲染子组件。
比如:
比如:

联调