Skip to content

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

Notifications You must be signed in to change notification settings

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

Repository files navigation

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:

# 安装所有依赖
$ yarn

# 启动开发
$ yarn dev

# 生产环境构建
$ yarn build

# 清除缓存(如果发现源码与webpack编译文件明显不一致,有可能是缓存脏数据)
$ yarn clear-cache

项目结构

.
├── .happypack                      // happypack缓存文件
├── bin                             // 代码生成脚本
├── builder                         // 构建工具
├── dist                            // 开发构建时,生成的临时文件,生产环境不用
├── local-default                   // 个性化配置,用户分模块打包、个人配置等,只开发模式有效,目前没启用,预留功能
├── public                          // 构建之后的代码,用户生产环境部署
├── src                             // 开发主要目录
│    ├── commons                    // 系统公共方法,组件
│    ├── frame                      // 页面框架,头部+左侧等
│    ├── mock                       // mock数据,截获ajax请求,便于前端单独调试
│    │   └── mockdata               // 模拟数据 mockjs
│    ├── pages                      // 业务页面,业务开发主要关系目录
│    │   ├── error                  // 一些error页面,404 403 401 等等
│    │   ├── examples               // 一些例子
│    │   └── home                   // 首页
│    ├── redux                      // redux 相关
│    │   ├── actions                // redux action定义
│    │   ├── reducers               // redux reducers定义目录
│    │   ├── store                  // redux store
│    │   └── actionTypes.js         // actions 和 reducers使用的types常量
│    ├── route                      // 路由 相关
│    ├── services                   // 前端服务,一般是ajax请求等一些封装,提供基础数据
│    ├── all-routes.js              // 脚本生成的路由配置文件
│    ├── App.jsx                    // 项目入口文件
│    ├── global.less                // 全局样式定义
│    ├── page-init-state.js         // 全局样式定义
│    ├── page-init-state.js         // 脚本生成的简化redux写法的初始化state
│    ├── page-routes.js             // 脚本生成的路由配置文件
│    └── variables.less             // 主题变量
├── static                          // 非构建依赖的静态文件
├── .babelrc
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── favicon.png
├── index.html
├── package.json
├── postcss.config.js
├── README.md
└── 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,使用/+作为分界,比如:

list页面:
export const PAGE_ROUTE = '/example/users'

list页面的添加按钮,跳转到添加页面,但是页面菜单选中状态要保持list页面状态

export const PAGE_ROUTE = '/example/users/+add'

页面头部

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

显示隐藏

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

修改标题

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

自定义面包屑导航

componentWillMount() {
    this.props.$actions.setPageBreadcrumbs([
        {
            key: 'zidingyi',
            path: '',
            text: '自定义',
            icon: 'fa-user',
        },
        {
            key: 'mianbaoxie',
            path: '',
            text: '面包屑',
            icon: 'fa-user',
        },
        {
            key: 'daohang',
            path: '',
            text: '导航',
            icon: 'fa-user',
        },
    ]);
}

前后端分离 ngnix配置 参考

# 服务地址
upstream api_service {
  server localhost:8080;
  keepalive 2000;
}
#
server {
    listen       80;
    server_name  localhost;
    location / {
      root /home/app/nginx/html; // 前端打包之后的文件存放路径
      index index.html;
      try_files $uri $uri/ /index.html; #react-router 防止页面刷新出现404
    }
    location ^~/api { // 代理ajax请求,前端的ajax请求配置了统一的baseUrl = ‘/api’
       proxy_pass http://api_service/;
       proxy_set_header Host  $http_host;
       proxy_set_header Connection close;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-Server $host;
    }
}

构建拆分

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

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

"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如下

module.exports = {
    // 业务页面所在目录,用来构建路由以及init state,字符串或者数组
    pagePath: './src/pages/**/*.jsx',
    // pagePath: [
    //     './src/pages/reserve/**/*.jsx',
    //     './src/pages/sale/**/*.jsx',
    // ],

    // 忽略文件,不进行构建,提供部分模块打包功能,一般是配合补充 pagePath 进行使用,字符串或者数组
    pageIgnore: [
        // '**/ActionsExample.jsx',
    ],

    // webpack配置,区分不同环境
    webpack: {
        base: {
            entry: {
                app: './src/App.jsx',
                login: './src/pages/login/Login.jsx',
            },
        },
        dev: {},
        prod: {},
        dll: {},
    },
};

TODO

  • 登录之后,获取菜单数据,并存入session中,由于页面头部是由菜单生成的,如果菜单是异步获取的,将会存在各种问题,所以进入系统时候保证菜单可用。 已经改为进入App之前获取菜单,这样刷新页面就可以获取最新菜单,不必重新登录。
  • 构建优化:css postcss的使用,自动添加前缀等功能
  • 是否使用 css module功能,好像加不上,antd不是module方式,如果使用module,antd less 构建会失败。 通过配置可以区分出那些模块使用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重构项目结构、构建流程 - 浏览器与webstorm 结合的调试
  • react-router v4
  • 菜单、页面标题、面包屑导航单独拆分成redux
  • zk-tookit 打包构建
  • 开发时,使用node做proxy,不使用ajax 的baseURL,后端不用解决跨域问题;
  • 提供不同结构的frame:单独头部菜单、单独左侧菜单、左侧+头部菜单、空框架等等;
  • eslint 开发时不强制,提交时强制,提高开发时效率,同时提交时保证代码质量;

About

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

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published