项目作者: zkboys

项目描述 :
管理系统架构,基于 antd + react + redux + webpack + ES6 的单页面应用
高级语言: HTML
项目地址: git://github.com/zkboys/react-antd-redux-webpack-es6-spa-boilerplate.git


react-antd-redux-webpack-es6-spa-boilerplate

管理系统架构,基于 antd + react + redux + webpack + ES6 的单页面应用

React
Ant Design
dva
GitHub issues
MIT

管理系统往往是大量的表单表格等页面,存在大量的体力劳动,基于长期的管理系统开发,整理出一套管理系统架构、组件、通用方法来提高开发效率。
可以以此为基础,快速创建管理系统项目。simple is all,make coding easy!
感谢ant design提供如此出色的UI库及设计思想,让开发变得简单很多!祝ant design越做越好!

喜欢就给个star,感谢您的鼓励与支持!

注:此库使用后编译(依赖具体项目的编译环境)

架构功能一览:

如果您想找华丽的UI,这个框架会让你失望,它目前只关注了如何简化编码,提高开发效率。

  1. UI基于antd,完整的登录、退出登录、菜单等结构。
  2. 前后端分离,前后端可以并行开发,前端单独部署。
  3. 基于webpack2.0进行构建,对构建进行了优化,提高rebuild速度,提高开发效率。
  4. 菜单、页面标题、面包屑导航自动获取+可配置。
  5. redux写法封装、简化的redux写法、与存储自动同步、异步redux写法、异常处理,相关文档在: src/redux/README.md。
  6. ajax自动提示封装、全局+局部配置、ajax高阶组件自动释放资源、前后端约定统一错误处理。
  7. 路由简化配置,页面直接声明一个PAGE_ROUTE变量,自动生成路由配置文件。相关文档在: src/route/README.md。
  8. 后端交互统一封装成service、提供基于restFull,提供BaseService基础方法、service高阶组件自动释放资源。
  9. mock规则可配置,快速切换mock数据与真实数据
  10. 基础CRUD代码生成,减少不必要的体力劳动。脚本在bin目录下。
  11. 列表页可配置,通过ListPage组件,通过简单的配置,可以生成列表页面。
  12. css 模块化,有效避免css命名冲突,提高css命令灵活性。
  13. 使用eslint 结合 webpack 统一代码规范,降低各个开发人员直接的沟通成本,提高代码质量。

开发环境

  1. node v7.2.1
  2. yarn v0.27.5
  3. 兼容windows/mac 还没在ubuntu上开发,未知。

安装、开发/生产构建

必须使用yarn进行构建。yarn可以更好的组织依赖,下载依赖速度更快,也许还需要翻墙。
使用npm或者淘宝的cnpm安装之后运行npm run dev会报错无法启动;

yarn:

  1. # 安装所有依赖
  2. $ yarn
  3. # 启动开发
  4. $ yarn dev
  5. # 生产环境构建
  6. $ yarn build
  7. # 清除缓存(如果发现源码与webpack编译文件明显不一致,有可能是缓存脏数据)
  8. $ yarn clear-cache

项目结构

  1. .
  2. ├── .happypack // happypack缓存文件
  3. ├── bin // 代码生成脚本
  4. ├── builder // 构建工具
  5. ├── dist // 开发构建时,生成的临时文件,生产环境不用
  6. ├── local-default // 个性化配置,用户分模块打包、个人配置等,只开发模式有效,目前没启用,预留功能
  7. ├── public // 构建之后的代码,用户生产环境部署
  8. ├── src // 开发主要目录
  9. ├── commons // 系统公共方法,组件
  10. ├── frame // 页面框架,头部+左侧等
  11. ├── mock // mock数据,截获ajax请求,便于前端单独调试
  12. └── mockdata // 模拟数据 mockjs
  13. ├── pages // 业务页面,业务开发主要关系目录
  14. ├── error // 一些error页面,404 403 401 等等
  15. ├── examples // 一些例子
  16. └── home // 首页
  17. ├── redux // redux 相关
  18. ├── actions // redux action定义
  19. ├── reducers // redux reducers定义目录
  20. ├── store // redux store
  21. └── actionTypes.js // actions 和 reducers使用的types常量
  22. ├── route // 路由 相关
  23. ├── services // 前端服务,一般是ajax请求等一些封装,提供基础数据
  24. ├── all-routes.js // 脚本生成的路由配置文件
  25. ├── App.jsx // 项目入口文件
  26. ├── global.less // 全局样式定义
  27. ├── page-init-state.js // 全局样式定义
  28. ├── page-init-state.js // 脚本生成的简化redux写法的初始化state
  29. ├── page-routes.js // 脚本生成的路由配置文件
  30. └── variables.less // 主题变量
  31. ├── static // 非构建依赖的静态文件
  32. ├── .babelrc
  33. ├── .eslintignore
  34. ├── .eslintrc.js
  35. ├── .gitignore
  36. ├── favicon.png
  37. ├── index.html
  38. ├── package.json
  39. ├── postcss.config.js
  40. ├── README.md
  41. └── yarn.lock

文件命名约定

  1. 文件夹小写英文加连字符”-“,比如:src/pages/user-center
  2. less文件、js文件 小写英文加连字符”-“,比如:user-center.lessuser-center.js
  3. jsx文件(组件),首字母大写,驼峰命名,比如:UserCenter.jsx

系统菜单激活状态

系统菜单的激活状态根据url地址,自动判定

菜单匹配分几种情况

  1. pathname 与菜单path精确匹配,直接使用此菜单
  2. pathname 的 /+ 之前部分与菜单path精确匹配,直接使用此菜单
  3. 没有匹配到菜单,使用系统上次菜单;
    上次菜单不存在,获取LocalStorage中保存的菜单节点;(每次匹配了菜单都要存入LS)
    LocalStorage中不存在,页面就无菜单状态(这种情况一般不存在);

如果是二级页面,比如添加页面,需要保持其父级页面菜单状态,菜单path需要写成parentPath/+childPath,使用/+作为分界,比如:

  1. list页面:
  2. export const PAGE_ROUTE = '/example/users'
  3. list页面的添加按钮,跳转到添加页面,但是页面菜单选中状态要保持list页面状态
  4. export const PAGE_ROUTE = '/example/users/+add'

页面头部

页面头部标题、面包屑导航系统会根据页面状态自动获取,但也可以控制显示隐藏、修改标题、修改面包屑。

显示隐藏

  1. componentWillMount() {
  2. this.props.$actions.hidePageHeader();
  3. }

修改标题

  1. componentWillMount() {
  2. this.props.$actions.setPageTitle('自定义页面标题');
  3. }

自定义面包屑导航

  1. componentWillMount() {
  2. this.props.$actions.setPageBreadcrumbs([
  3. {
  4. key: 'zidingyi',
  5. path: '',
  6. text: '自定义',
  7. icon: 'fa-user',
  8. },
  9. {
  10. key: 'mianbaoxie',
  11. path: '',
  12. text: '面包屑',
  13. icon: 'fa-user',
  14. },
  15. {
  16. key: 'daohang',
  17. path: '',
  18. text: '导航',
  19. icon: 'fa-user',
  20. },
  21. ]);
  22. }

前后端分离 ngnix配置 参考

  1. # 服务地址
  2. upstream api_service {
  3. server localhost:8080;
  4. keepalive 2000;
  5. }
  6. #
  7. server {
  8. listen 80;
  9. server_name localhost;
  10. location / {
  11. root /home/app/nginx/html; // 前端打包之后的文件存放路径
  12. index index.html;
  13. try_files $uri $uri/ /index.html; #react-router 防止页面刷新出现404
  14. }
  15. location ^~/api { // 代理ajax请求,前端的ajax请求配置了统一的baseUrl = ‘/api
  16. proxy_pass http://api_service/;
  17. proxy_set_header Host $http_host;
  18. proxy_set_header Connection close;
  19. proxy_set_header X-Real-IP $remote_addr;
  20. proxy_set_header X-Forwarded-Server $host;
  21. }
  22. }

构建拆分

基于配置,进行不同项目的打包构建,解决不同项目,但是类似,有很多通用组件,但是要单独发布的情景;
如果项目相差较大,没有太多的公共部分,还是建议单独建立一个项目。

构建可以传入config文件,基于config文件可以构建出不同的项目

  1. "dev": "yarn run clear-cache && yarn run dll && cross-env NODE_ENV=development node ./builder/dev-server.js --cfg ./xxx.config.js",

xxx.config.js如下

  1. module.exports = {
  2. // 业务页面所在目录,用来构建路由以及init state,字符串或者数组
  3. pagePath: './src/pages/**/*.jsx',
  4. // pagePath: [
  5. // './src/pages/reserve/**/*.jsx',
  6. // './src/pages/sale/**/*.jsx',
  7. // ],
  8. // 忽略文件,不进行构建,提供部分模块打包功能,一般是配合补充 pagePath 进行使用,字符串或者数组
  9. pageIgnore: [
  10. // '**/ActionsExample.jsx',
  11. ],
  12. // webpack配置,区分不同环境
  13. webpack: {
  14. base: {
  15. entry: {
  16. app: './src/App.jsx',
  17. login: './src/pages/login/Login.jsx',
  18. },
  19. },
  20. dev: {},
  21. prod: {},
  22. dll: {},
  23. },
  24. };

TODO

  • 登录之后,获取菜单数据,并存入session中,由于页面头部是由菜单生成的,如果菜单是异步获取的,将会存在各种问题,所以进入系统时候保证菜单可用。
    1. 已经改为进入App之前获取菜单,这样刷新页面就可以获取最新菜单,不必重新登录。
  • 构建优化:css postcss的使用,自动添加前缀等功能
  • 是否使用 css module功能,好像加不上,antd不是module方式,如果使用module,antd less 构建会失败。
    1. 通过配置可以区分出那些模块使用css module,那些不使用。
  • 添加事件,移除事件的高阶组件
  • redux 中数据,实现部分数据同步到localStorage中,目前是可以选择性恢复,可以满足需求
  • source-map改如何使用
  • 左侧菜单可拖动缩放宽度
  • zk-react 开发模式构建慢问题,升级到webpack2.0,添加了一些优化
  • antd 通用校验规则整理到zk-react中
  • antd edit-cell其他表单元素完善、 可配置form组件(可用于查询条件、简单的form)
  • antd 自定义异步校验,多个异步校验互相干扰问题 可以使用Promise.all包装各个请求
  • 系统注入到props中的变量统一使用’$’开头,比如$ajax $event $domEvent $service $actions
  • css module class name 长短问题
  • 字体图标,团队有条件还是定制的好,全部引入会多出300~400KB。
  • 修改less时可以hot reload ,修改jsx为什么直接reload?
  • antd 图标本地部署问题:缓存问题,antd.less需要全部引入,会多550KB的css代码
  • docker 前端生产环境部署
  • 菜单匹配时,如果path携带参数,怎么能匹配成功?
  • css module=true background: url(); 问题 Module not found: Error: Can’t resolve ‘login-bg.jpg’
  • 测试:单元测试,端对端测试
  • 整理完善demo、文档,使用jsdoc?es6支持情况如何?
  • TypeScript + immutable 重构,团队人员情况,学习成本,开发成本?
  • 基于create-react-app重构项目结构、构建流程
    1. - 浏览器与webstorm 结合的调试
  • react-router v4
  • 菜单、页面标题、面包屑导航单独拆分成redux
  • zk-tookit 打包构建
  • 开发时,使用node做proxy,不使用ajax 的baseURL,后端不用解决跨域问题;
  • 提供不同结构的frame:单独头部菜单、单独左侧菜单、左侧+头部菜单、空框架等等;
  • eslint 开发时不强制,提交时强制,提高开发时效率,同时提交时保证代码质量;