1.2.1 umi 使用
umi,中文可发音为乌米,是一个可插拔的企业级 react 应用框架。umi 以路由为基础的,支持类 next.js 的约定式路由,以及各种进阶的路由功能,并以此进行功能扩展,比如支持路由级的按需加载。然后配以完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求,目前内外部加起来已有 50+ 的插件。
📦 开箱即用,内置 react、react-router 等 🏈 类 next.js 且功能完备的路由约定,同时支持配置的路由方式 🎉 完善的插件体系,覆盖从源码到构建产物的每个生命周期 🚀 高性能,通过插件支持 PWA、以路由为单元的 code splitting 等 💈 支持静态页面导出,适配各种环境,比如中台业务、无线业务、egg、支付宝钱包、云凤蝶等 🚄 开发启动快,支持一键开启 dll 和 hard-source-webpack-plugin 等 🐠 一键兼容到 IE9,基于 umi-plugin-polyfills 🍁 完善的 TypeScript 支持,包括 d.ts 定义和 umi test 🌴 与 dva 数据流的深入融合,支持 duck directory、model 的自动加载、code splitting 等等
install
# 全局安装 umi
yarn global add umi
使用 yarn 安装后全局还是不能使用 umi,
[解决方法](https://github.com/fairyly/mynodejs/blob/gh-pages/1.2.5%20%E8%A7%A3%E5%86%B3yarn%E5%85%A8%E5%B1%80%E5%AE%89%E8%A3%85%E6%A8%A1%E5%9D%97%E5%90%8E%E4%BD%86%E4%BB%8D%E6%8F%90%E7%A4%BA%E6%97%A0%E6%B3%95%E6%89%BE%E5%88%B0%E5%91%BD%E4%BB%A4%E7%9A%84%E9%97%AE%E9%A2%98.md)
最后改用 npm i -g umi
出现问题:
npm ERR! code ETARGET
npm ERR! notarget No matching version found for @babel/generator@^7.2.2
npm ERR! notarget In most cases you or one of your dependencies are requesting
npm ERR! notarget a package version that doesn't exist.
npm ERR! notarget
npm ERR! notarget It was specified as a dependency of '@babel/core'
npm ERR! notarget
由于原来使用的是公司的源,就切换到 淘宝源之后重新安装就可以了
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
usage(test)
建个空目录:
mkdir myapp && cd myapp
通过 umi g 创建一些页面:
$ umi g page index
$ umi g page users
2
3
4
5
6
7
8
通过脚手架创建项目
mkdir myapp && cd myapp
npm create umi
选择 app
? Do you want to use typescript? (y/N) n
选择 antd
创建完成
npm start 启动
2
3
4
5
6
7
8
9
10
11
12
13
14
目录
一个复杂应用的目录结构如下:
.
├── 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.umi 中会生成一些配置文件,如本地路由配置等
注意:(不要直接在这里修改代码,umi 重启或者 pages 下的文件修改都会重新生成这个文件夹下的文件。)
路由
介绍的路由使用可以在 umi-examples/routes 和 umi-examples/routes-via-config 里找到示例代码
约定式路由
约定 pages 下所有的 js、jsx、ts 和 tsx 文件即路由。
基础路由
假设 pages 目录结构如下:
+ pages/
+ users/
- index.js
- list.js
- index.js
2
3
4
5
那么,umi 会自动生成路由配置如下:
[
{ path: '/', component: './pages/index.js' },
{ path: '/users/', component: './pages/users/index.js' },
{ path: '/users/list', component: './pages/users/list.js' },
]
2
3
4
5
动态路由
umi 里约定,带 $ 前缀的目录或文件为动态路由。
比如以下目录结构:
+ pages/
+ $post/
- index.js
- comments.js
+ users/
$id.js
- index.js
2
3
4
5
6
7
会生成路由配置如下:
[
{ 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' },
]
2
3
4
5
6
可选的动态路由
umi 里约定动态路由如果带 $ 后缀,则为可选动态路由。
比如以下结构:
+ pages/
+ users/
- $id$.js
- index.js
2
3
4
会生成路由配置如下:
[
{ path: '/': component: './pages/index.js' },
{ path: '/users/:id?': component: './pages/users/$id$.js' },
]
2
3
4
嵌套路由
umi 里约定目录下有 _layout.js 时会生成嵌套路由,以 _layout.js 为该目录的 layout 。
比如以下目录结构:
+ pages/
+ users/
- _layout.js
- $id.js
- index.js
2
3
4
5
会生成路由配置如下:
[
{ path: '/users', component: './pages/users/_layout.js',
routes: [
{ path: '/users/', component: './pages/users/index.js' },
{ path: '/users/:id', component: './pages/users/$id.js' },
],
},
]
2
3
4
5
6
7
8
全局 layout
约定 src/layouts/index.js 为全局路由,返回一个 React 组件,通过 props.children 渲染子组件。
比如:
export default function(props) {
return (
<>
<Header />
{ props.children }
<Footer />
</>
);
}
2
3
4
5
6
7
8
9
不同的全局 layout
你可能需要针对不同路由输出不同的全局 layout,umi 不支持这样的配置,
但你仍可以在 layouts/index.js 对 location.path 做区分,渲染不同的 layout 。
比如想要针对 /login 输出简单布局,
export default function(props) {
if (props.location.pathname === '/login') {
return <SimpleLayout>{ props.children }</SimpleLayout>
}
return (
<>
<Header />
{ props.children }
<Footer />
</>
);
}
2
3
4
5
6
7
8
9
10
11
12
13
404 路由
约定 pages/404.js 为 404 页面,需返回 React 组件。
比如:
export default () => {
return (
<div>I am a customized 404 page</div>
);
};
2
3
4
5
注意:开发模式下,umi 会添加一个默认的 404 页面来辅助开发,但你仍然可通过精确地访问 /404 来验证 404 页面。
配置式路由
如果你倾向于使用配置式的路由,可以配置 routes ,此配置项存在时则不会对 src/pages 目录做约定式的解析。
比如:
export default {
routes: [
{ path: '/', component: './a' },
{ path: '/list', component: './b', Routes: ['./routes/PrivateRoute.js'] },
{ path: '/users', component: './users/_layout',
routes: [
{ path: '/users/detail', component: './users/detail' },
{ path: '/users/:id', component: './users/id' }
]
},
],
};
2
3
4
5
6
7
8
9
10
11
12
注意:component 是相对于 src/pages 目录的
权限路由
umi 的权限路由是通过配置路由的 Routes 属性来实现。约定式的通过 yaml 注释添加,配置式的直接配上即可。
比如有以下配置:
[
{ path: '/', component: './pages/index.js' },
{ path: '/list', component: './pages/list.js', Routes: ['./routes/PrivateRoute.js'] },
]
2
3
4
然后 umi 会用 ./routes/PrivateRoute.js 来渲染 /list。
./routes/PrivateRoute.js 文件示例:
export default (props) => {
return (
<div>
<div>PrivateRoute (routes/PrivateRoute.js)</div>
{ props.children }
</div>
);
}
2
3
4
5
6
7
8
启用 Hash 路由
umi 默认是用的 Browser History,如果要用 Hash History,需配置:
export default {
history: 'hash',
}
2
3