Ant Design Pro 是一个基于 umi、dva 和 ant design 的开箱即用的中台前端/设计解决方案。
一、umi和dva
1.1、什么是umi
umi,中文可发音为乌米,是一个可插拔的企业级 react 应用框架。umi 以路由为基础的,支持类 next.js 的约定式路由,以及各种进阶的路由功能,并以此进行功能扩展,比如支持路由级的按需加载。然后配以完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求,目前内外部加起来已有 50+ 的插件。
上面一段来自umi官网介绍,从上面我们得到一个重要信息,umi的一个重要功能就是路由配置。 此外umi整合了webpack的功能,umi相比webpack增加了运行时的能力,同时帮助我们配置了很多 webpack 的预设。也减少了 webpack 升级导致的问题:
- plugin-access,权限管理
- plugin-analytics,统计管理
- plugin-antd,整合 antd UI 组件
- plugin-initial-state,初始化数据管理
- plugin-layout,配置启用 ant-design-pro 的布局
- plugin-locale,国际化能力
- plugin-model,基于 hooks 的简易数据流
- plugin-request,基于 umi-request 和 umi-hooks 的请求方案
1.2、什么是dva
dva 首先是一个基于 redux 和 redux-saga 的数据流方案,可以和umi完美结合。
1.3、 什么是redux-saga
redux-saga是一个用于管理应用程序 Side Effect(副作用,例如异步获取数据,访问浏览器缓存等)的 library,它的目标是让副作用管理更容易,执行更高效,测试更简单,在处理故障时更容易。
可以想像为,一个 saga 就像是应用程序中一个单独的线程,它独自负责处理副作用。redux-saga是一个 redux 中间件,意味着这个线程可以通过正常的 redux action 从主应用程序启动,暂停和取消,它能访问完整的 redux state,也可以 dispatch redux action。
redux-saga 使用了 ES6 的 Generator 功能,让异步的流程更易于读取,写入和测试。(如果你还不熟悉的话,这里有一些介绍性的链接) 通过这样的方式,这些异步的流程看起来就像是标准同步的 Javascript 代码。(有点像 async
/await
,但 Generator 还有一些更棒而且我们也需要的功能)。
你可能已经用了 redux-thunk 来处理数据的读取。不同于 redux thunk,你不会再遇到回调地狱了,你可以很容易地测试异步流程并保持你的 action 是干净的。
1.3.1 安装
npm install --save redux-saga
1.3.2 使用示例
假设我们有一个 UI 界面,在单击按钮时从远程服务器获取一些用户数据(为简单起见,我们只列出 action 触发代码)。
class UserComponent extends React.Component {
...
onSomeButtonClicked() {
const { userId, dispatch } = this.props
dispatch({type: 'USER_FETCH_REQUESTED', payload: {userId}})
}
...
}
这个组件 dispatch 一个 plain Object 的 action 到 Store。我们将创建一个 Saga 来监听所有的 USER_FETCH_REQUESTED action,并触发一个 API 调用获取用户数据。
sagas.js:
import { call, put, takeEvery, takeLatest } from 'redux-saga/effects'
import Api from '...'
// worker Saga : 将在 USER_FETCH_REQUESTED action 被 dispatch 时调用
function* fetchUser(action) {
try {
const user = yield call(Api.fetchUser, action.payload.userId);
yield put({type: "USER_FETCH_SUCCEEDED", user: user});
} catch (e) {
yield put({type: "USER_FETCH_FAILED", message: e.message});
}
}
/*
在每个 `USER_FETCH_REQUESTED` action 被 dispatch 时调用 fetchUser
允许并发(译注:即同时处理多个相同的 action)
*/
function* mySaga() {
yield takeEvery("USER_FETCH_REQUESTED", fetchUser);
}
/*
也可以使用 takeLatest
不允许并发,dispatch 一个 `USER_FETCH_REQUESTED` action 时,
如果在这之前已经有一个 `USER_FETCH_REQUESTED` action 在处理中,
那么处理中的 action 会被取消,只会执行当前的
*/
function* mySaga() {
yield takeLatest("USER_FETCH_REQUESTED", fetchUser);
}
export default mySaga;
为了能跑起 Saga,我们需要使用 redux-saga 中间件将 Saga 与 Redux Store 建立连接。
main.js:
import { createStore, applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'
import reducer from './reducers'
import mySaga from './sagas'
// create the saga middleware
const sagaMiddleware = createSagaMiddleware()
// mount it on the Store
const store = createStore(
reducer,
applyMiddleware(sagaMiddleware)
)
// then run the saga
sagaMiddleware.run(mySaga)
// render the application
更多使用细节请移步官网。
二、脚手架使用
2.1、初始化脚手架
新建一个空的文件夹作为项目目录,并在目录下使用 create umi 来快速的初始化脚手架。
# 使用 npm
npm create umi react-big-screen
如果下载比较慢,可以先配置npm阿里源:
npm config set registry https://registry.npm.taobao.org/
按照 umi 脚手架的引导,第一步先选择 ant-design-pro:
? Select the boilerplate type (Use arrow keys)
> ant-design-pro - Create project with a layout-only ant-design-pro boilerplate, use together with umi block.
app - Create project with a simple boilerplate, support typescript.
block - Create a umi block.
library - Create a library with umi.
plugin - Create a umi plugin.
选择 antd 的版本,4 或者 5。
? Select the boilerplate type ant-design-pro
? � Be the first to experience the new umi@3 ?
> Pro V5
Pro V4
安装依赖:
cd react-big-screen && cnpm install
2.2、启动脚手架
开启 Umi UI(可选):
npm start
使用admin/ant.design登录系统:
通过npm start我们就可以启动服务,那你可能会好奇执行这个命令为什么就可以启动我们的服务呢?
npm start 运行的是package.json中script块start对应的命令,打开package.json,你会发现我们实际执行的是如下执行:
cross-env是用来解决多环境问题的,你可暂且忽略。重点关注umi dev。
umi 是一个软连接到umi.js的文件:
#!/usr/bin/env node const resolveCwd = require('resolve-cwd'); const { name, bin } = require('../package.json'); const localCLI = resolveCwd.silent(`${name}/${bin['umi']}`); if (!process.env.USE_GLOBAL_UMI && localCLI && localCLI !== __filename) { const debug = require('@umijs/utils').createDebug('umi:cli'); debug('Using local install of umi'); require(localCLI); } else { require('../lib/cli'); }
也就是其实执行的umi/lib/cli.js文件, 关键部分代码:
_asyncToGenerator(function* () { try { switch (args._[0]) { case 'dev': const child = (0, _fork.default)({ scriptPath: require.resolve('./forkedDev') }); // ref: // http://nodejs.cn/api/process/signal_events.html // https://lisk.io/blog/development/why-we-stopped-using-npm-start-child-processes process.on('SIGINT', () => { child.kill('SIGINT'); // ref: // https://github.com/umijs/umi/issues/6009 process.exit(0); }); process.on('SIGTERM', () => { child.kill('SIGTERM'); process.exit(1); }); break; default: const name = args._[0]; if (name === 'build') { process.env.NODE_ENV = 'production'; } yield new _ServiceWithBuiltIn.Service({ cwd: (0, _getCwd.default)(), pkg: (0, _getPkg.default)(process.cwd()) }).run({ name, args }); break; } } catch (e) { console.error(_utils().chalk.red(e.message)); console.error(e.stack); process.exit(1); } })();
2.3、开发计划
接下来我将花一个礼拜的时间带领大家开发一个报警管理平台:
2.4、代码下载
© 著作权归作者所有
发表评论