前言
最近做迭代的时候接触到公司的一个小项目是用的umi
框架,所以这里对umi
框架做一个简单的介绍,也算是学习笔记吧。
一、关于umi
umi
,中文可发音为乌米,是一个可插拔的企业级 react 应用框架。umi
以路由为基础的,支持类next.js
的约定式路由,以及各种进阶的路由功能,并以此进行功能扩展,比如支持路由级的按需加载。
二、创建umi
项目
这里先介绍一下项目的创建,你可以通过 yarn create umi
或 npm create umi
以及使用 create-umi
脚手架。推荐使用 yarn create
命令,能确保每次使用最新的脚手架。
使用create-umi
脚手架
1、全局安装脚手架
npm i craete-umi -g
2、选择 app
创建一个umi
应用
create-umi umi-app
不使用脚手架
直接使用npm
命令创建。注意:使用脚手架的时候会将项目中所有文件放在 umi-app
文件夹中,而不使用脚手架的时候,会将项目文件写入当前终端文件夹下,所以不使用脚手架创建项目的时候,需要新建一个文件夹,在该文件夹目录终端下创建项目。
npm create umi
三、目录作用的介绍
以下是umi
项目简单的目录结构,我将会依次介绍几个主要文件的作用。
.
├── 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
├── app.js // 运行时配置文件
├── .umirc.js // umi 配置,同 config/config.js,二选一
├── .env // 环境变量
└── package.json
dist
默认打包输出路径,可通过配置outputPath
修改。
mock
这个目录比较有意思,umi
会将该目录下的所有.js
文件解析成mock
文件,举个例子。
在mock下新建person.js
如下
export default {
'/api/users': {
name: 'rinvay'
}
}
那么访问浏览器的 http://localhost:8000/api/users
就能得到 {name:'rinvay'}
数据了,是不是很神奇。
src
约定 src
为源码目录,如果不存在 src
目录,则当前目录会被作为源码目录,也就是有无src
目录都是一样的。
src/layouts/index.js
全局布局,在路由的外面嵌套一成路由。
src/pages
pages下的所有js、jsx、ts和tsx文件即路由,这点和Next.js也是一样的。
config/config.js 和 .umirc.js
这两个是 umi
的配置文件,注意:只能二选一,不可以共同存在。
src/global.css
此文件不走 css modules
,且会自动被引入,可以在这里写全局样式,以及做样式覆盖。
这里解释一下,也就是说,在 pages 中的组件中引入样式默认走 css modules
,如下:
// 引入css
import styles from './index.css';
// 使用css ---> styles.title
<h1 className={styles.title}>Yay! Welcome to umi!</h1>
src/global.js
此文件会在入口文件的最前面被自动引入,可以在这里加载补丁,做一些初始化的操作等。
四、路由
约定式路由
Umi的路由即pages
文件夹下的文件。比如有如下的pages
文件夹。
+ pages/
+ users/
- index.js
- list.js
- index.js
那么在pages
下的.umi
下的router.js
文件中就会大致生成如下的路由文件。
[
{ path: '/', component: './pages/index.js' },
{ path: '/users/', component: './pages/users/index.js' },
{ path: '/users/list', component: './pages/users/list.js' },
]
这是umi
最基本的路由。
动态路由
umi
里面约定带$
前缀的目录或文件为动态路由
+ pages
+ $post
- index.js
+ users
$id.js
会生成的路由配置文件如下
[
{ path: '/users/:id', component: './pages/users/$id.js' },
{ path: '/:post/', component: './pages/$post/index.js' },
]
这个时候,我们可以在 $id.js
文件中,通过组件的props
中的match
属性的params
对象中找到对应的参数。比如:我们访问/users/678
这个路由 ,我们拿到的match
对象如下:
{
isExact: true
params: {id: "678"}
path: "/user/:id"
url: "/user/678"
}
通过注释拓展路由
这个是umi
中比较有意思的一个功能,它约定路由文件的首个注释如果包含 yaml
格式的配置,则会被用于扩展路由,特别是权限路由。假如我们有如下场景,进入网址首页需要鉴权,我们在首页index.tsx
中配置:
/**
* title: Index Page
* Routes:
* - ./src/routes/private.js
*/
import React from 'react';
export default function() {
return <h1>Index Page</h1>
}
这样我们的首页组件就是 routes/private.js
中的一个子组件。然后我们在 private.js
中添加鉴权的逻辑就行了。
import React from 'react';
export default function PrivateRoute(props) {
const {children} = props
const token = true
return (
<React.Fragment>
<h1>下面的组件需要鉴权渲染</h1>
{token && children}
</React.Fragment>
)
}
五、配置
umi
允许在 .umirc.js
或 config/config.js
(二选一,.umirc.js
优先)中进行配置,支持 ES6
语法。这里就简单说一下常用的几个配置,详情请查看 UmiJS配置 。
插件配置
export default {
plugins: [
// 有参数的情况,这里配置了我们项目中常用的 dva 和 antd 插件
[
'umi-plugin-react',
{
dva: true,
antd: true,
},
],
],
};
路由类型配置
指定 history 类型,可选 browser
、hash
和 memory
。至于什么是memory
,可以看看 前端路由实现思路。
export default {
history: 'hash',
};
targets
配置浏览器最低版本,会自动引入 polyfill
和做语法转换,配置的 targets 会和合并到默认值,所以不需要重复配置。
// 兼容 ie11
export default {
targets: {
ie: 11,
},
};
以上就是Umi
初步的一个简单的介绍。