React实战企业管理项目系列

(二)React系列-实战01:开发热身准备

背景

企业管理系统作为供企业内部人员使用的应用,在浏览器适配性方面的要求并没有供普通用户使用的应用那么严格,这为我们选择现代的 JavaScript 框架提供了一定的便利。于是接下来的问题就变为了在 React、Angular、Vue 这三大 JavaScript 框架中应当选择哪一个?
这里不做三种框架的对比,互相也没有可比性,各有所长;我认为我是想用React打造企业管理系统,进这一个理由已经表明了我要使用的React框架。
另外,一个倾向是React对于ts的倾向性更好,最后还有一点值得比较的就是二者对于 TypeScript 的友好程度。React 社区在 TypeScript 方面的探索以及积累的经验相对而言要比 Vue 社区更多一些,而 Vue 则是在 2.5 版本之后才完善了自身对于 TypeScript 的支持。所以如果你的技术选型中有 TypeScript 的话,在渲染框架层面 React 可能会是一个更好的选择。

Node.js

我本地的Node.js版本是10.14.2。推荐使用 8.10.0 或 9.10.0 以上的版本,否则将不能够兼容 ESLint 当前最新的 5.0 +版本。

包管理工具

我们在安装项目依赖的时候可以使用默认的npm,也可以使用yarn,这里要说一下,Yarn自身强大的cache功能,可以再重复安装相同依赖时起到加速的作用。

第三方依赖

本项目中需要用到的底单房依赖都在项目的package.json文件中,可以使用 npm install 或者是npm i 安装依赖即可。下面列出一些本地重要的依赖版本
React实战企业管理项目系列
这里仅仅是我本地的部分重要依赖,一切实际项目中三方以来为准。

从0开始创建一个纯净的脚手架

创建package.json

首先我们新建一个文件夹,可以手动创建也可以命令创建(mkdir myApp),进入刚创建的文件夹下,执行命令 npm init,就会出现下边的目录。
React实战企业管理项目系列
这个时候我们的文件夹下就会自动创建一个package.json文件
React实战企业管理项目系列
打开这个文件,是个很纯净的第三方依赖.
React实战企业管理项目系列

创建webpack.[mode|config].js文件

我们知道在创建一个webpack配置文件,可以手动创建一个webpack.dev.js或者任意一种webpack.[mode].js的文件,那么今天我今天说的是使用命令的方式创建一个配置的完美方案,全局安装webpack和webpack-cli 进入项目目录执行 webpack init
React实战企业管理项目系列
这个时候我们发现我们的项目目录发生了变化,多出来一个webpack.dev.js文件
React实战企业管理项目系列

安装第三方依赖

Babel:Babel 是一个 JavaScript 编译器。我们这里是说在构建工具中使用。通过npm 安装一系列的依赖 npm install --save babel-***;然后配置config文件使用babel;
代码:

{       
 	test: /\.(jsx|js)$/,       
  	exclude: /node_modules/,        
	use: {          
 		 	loader: 'babel-loader' 
     }      
 }

虽然已经配置好了 Babel ,但并没有让它真正生效。在项目的根目录中创建一个 .babelrc 文件并启用一些插件;接下来要使用es2015转化配置你可以使用 babel-preset-env ;为了让 preset 生效,你需要像下面这样定义你的 .babelrc 文件

"presets": [  
  	"@babel/env" 
 ],

发现这样列出来有点过于细致了,下边直接把需要的简单罗列一下:

  • react: 16.4.2
  • react-dom: 16.4.2
  • redux: 4.0.0
  • redux-thunk: 2.3.0
  • react-router-dom: 4.3.1
  • connected-react-router: 4.3.0
  • antd: 3.6.6
  • webpack: 4.16.5
  • babel-core: 6.26.3
  • eslint: 5.3.0
  • jest: 23.4.2
  • axios:0.18.0
    但是一般开发者会定时对使用的第三方依赖进行升级,但因为第三方依赖的更新速度较快,所以上面列出的第三方依赖版本可能会与实际示例项目中的有所出入,一切以实际示例项目中的 package.json 和 yarn.lock 为准。
    这里要强调一下redux的一些知识;随着 JavaScript 单页应用开发日趋复杂,JavaScript 需要管理比任何时候都要多的 state (状态)。 这些 state 可能包括服务器响应、缓存数据、本地生成尚未持久化到服务器的数据,也包括 UI 状态,如**的路由,被选中的标签,是否显示加载动效或者分页器等等。
    管理不断变化的 state 非常困难。如果一个 model 的变化会引起另一个 model 变化,那么当 view 变化时,就可能引起对应 model 以及另一个 model 的变化,依次地,可能会引起另一个 view 的变化。直至你搞不清楚到底发生了什么。state 在什么时候,由于什么原因,如何变化已然不受控制。 当系统变得错综复杂的时候,想重现问题或者添加新功能就会变得举步维艰。
    Redux 试图让 state 的变化变得可预测。这些限制条件反映在 Redux 的三大原则中;
  • 单一数据源:整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
  • State 是只读的:唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
  • 使用纯函数来执行修改:为了描述 action 如何改变 state tree ,你需要编写 reducers。
    下面我们结合这个原则,设计本项目的状态管理机制:
createStore
function createStore(history, preloadedState = {}) {
  // enhancers
  let composeEnhancers = compose;

  if (typeof window !== 'undefined') {
    // eslint-disable-next-line no-underscore-dangle
    composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
  }

  // middlewares
  const middlewares = [routerMiddleware(history), reduxThunk];

  const store = createReduxStore(connectRouter(history)(combineReducers({
    router: connectRouter(history),
    home,
    user,
    app
  })), preloadedState, composeEnhancers(applyMiddleware(...middlewares)), );

  return {
    store,
    history,
    routes
  };
}
action
function login() {
  return {
    type: 'LOGIN',
    payload: true,
  };
}

export default {
  login,
};
createReducer
function createReducer(defaultState, handlers) {
  if (typeof defaultState !== 'function') {
    throw new Error('[createReducer] defaultState should be a function');
  }

  function reducer(state = defaultState(), action = {}) {
    if (!action || typeof action.type !== 'string') {
      return state;
    }

    const handler = get(handlers, action.type);

    if (typeof handler === 'function') {
      return handler(state, action);
    }

    return state;
  }

  reducer.defaultState = defaultState;
  reducer.handlers = handlers;

  return reducer;
}
reducer
import createReducer from 'utils/createReducer';

const defaultState = () => ({
  isLogin: false,
});

export default createReducer(defaultState, {});

项目目录结构

最后经过我们对项目的梳理和理解,会搭建出一套清晰的项目目录;如下图

参考资料

如果感觉在学习或者使用一些新的框架有比较吃力的感觉,那建议学习一下下边的入门教程

  1. pure render:阿里数据中台前端团队分享前端相关经验。
  2. 前端精读评论:阿里数据中台前端团队分享前端界的好文精读。
  3. 前端新能源:分享前端有深度的新思想和新方法。
  4. 蚂蚁金服体验科技:探索极致用户体验与最佳工程实践。

参考代码

基本脚手架:https://github.com/wg-paddme/reactGeneration

总结:

本节笔记简单讲述了一下使用react搭建一个脚手架工具;下一节详细讲解项目脚手架的每个模块及功能和如何使用的。