Umi学习记录(一)

1,252 阅读5分钟

前言

最近做迭代的时候接触到公司的一个小项目是用的umi框架,所以这里对umi框架做一个简单的介绍,也算是学习笔记吧。

一、关于umi

umi,中文可发音为乌米,是一个可插拔的企业级 react 应用框架。umi 以路由为基础的,支持类 next.js 的约定式路由,以及各种进阶的路由功能,并以此进行功能扩展,比如支持路由级的按需加载。

二、创建umi项目

这里先介绍一下项目的创建,你可以通过 yarn create uminpm 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.jsconfig/config.js (二选一,.umirc.js 优先)中进行配置,支持 ES6 语法。这里就简单说一下常用的几个配置,详情请查看 UmiJS配置

插件配置
export default {
  plugins: [
    // 有参数的情况,这里配置了我们项目中常用的 dva 和 antd 插件
    [
      'umi-plugin-react',
      {
        dva: true,
        antd: true,
      },
    ],
  ],
};
路由类型配置

指定 history 类型,可选 browserhashmemory。至于什么是memory,可以看看 前端路由实现思路

export default {
  history: 'hash',
};
targets

配置浏览器最低版本,会自动引入 polyfill 和做语法转换,配置的 targets 会和合并到默认值,所以不需要重复配置。

// 兼容 ie11
export default {
  targets: {
    ie: 11,
  },
};

以上就是Umi初步的一个简单的介绍。