又一篇React实践【v16.0 +】

1,494 阅读3分钟
路漫漫其修远兮,吾将上下而求索。

背景

完全是出于实践的目的,在一个小业务中,将最新的react工程撸了一遍。【虽说是小业务,两个人也开发了近一周,七个工作日。】

贡献

于是有了这篇文章和【开箱即用】的脚手架工程,其中Options的选项,可以自行移除。不过好消息是这个脚手架工程,我将跟进维护,力保第一时间和react以及其生态周边的库在版本上保持一致。关于react v16.x react-router v4.x的资源,在网路上都有很多,这里就不重复贴了,想说明的是,官网肯定是第一去处。

【开箱即用】icepy/fighting

  • react v16.0 +
  • react-router 4.x
  • webpack 3.x
  • redux

Options

  • ant design
  • less
  • iconfont
  • mock server
  • axios
  • 钉钉H5 SDK

fighting 使用MIT协议,欢迎过来添砖加瓦。

正题

在开始准备用v16.x写业务之前,还是下了一番苦工,花了一天时间大概的扫了一遍和其他东西的契合度,这才敢下决心试试,不然还真会坑了自己。

由于在v15.x的版本中已经开始使用PureComponent,于是在v16.x中依然沿用着PureComponent,整体上来看v16.x更多的是在“内核”上的改进,书写过程中很好的和上一个版本的知识积累契合,只是多了一些不同的东西,比如错误捕获【生命周期中的一个方法】,直接返回数组等。在react上真正花了点时间的是在表单的处理上,一直到最后发布上线才解决掉那行警告。如果你可以阅读到fighting项目,基本上可以了解到我是怎么看待这个项目的。

标准的redux,定义action,reducers,使用 redux-thunk 来做异步处理。

// constants.js
export const DEFAULT_SYNC_DEFAULT = 'DEFAULT_SYNC_DEFAULT';
export const DEFAULT_ASYNC_DEFAULT = 'DEFAULT_ASYNC_DEFAULT';

// actions
import { DEFAULT_SYNC_DEFAULT, DEFAULT_ASYNC_DEFAULT } from './constants';

export const getDefault = (params) => {
  return {
    type: DEFAULT_SYNC_DEFAULT,
    payload: {
      data: 'wower'
    }
  }
}

export const getAsyncDefault = (params) => (dispatch) => {
  setTimeout(() => {
    dispatch((() => {
      return {
        type: DEFAULT_ASYNC_DEFAULT,
        payload: {
          data: 'icepy'
        }
      }
    })())
  },2000)
}

// reducers
import { DEFAULT_SYNC_DEFAULT, DEFAULT_ASYNC_DEFAULT } from './constants';

const initState = {
  name: '',
  asyncName: '...'
};

export default function defaultReducers(state = initState, action){
  const { type, payload } = action;
  switch (type){
    case DEFAULT_SYNC_DEFAULT:
      return { ...state, name: payload.data }
    case DEFAULT_ASYNC_DEFAULT:
      return { ...state, asyncName: payload.data}
    default:
      return { ...state}
  }
}

构建基于webpack 3.x来编写,并且对样式进行了autoprefixer处理。

Bash

提炼了三个命令来完成项目的开发:

$ npm start // 项目启动
$ npm run mock-server  // 启动mock服务器
$ npm run build  // 打包可以发布的资源

目录结构

顶级目录结构如下:

  • src 项目源文件
  • build 构建脚本
  • config 构建脚本依赖的配置信息
  • dist 构建完成可发布的资源目录

src 目录结构如下:

  • components 公共组件
  • globals 公共reducers
  • routers 路由
  • containers 页面级别的组件
  • styles 公共样式
  • shared 抽象出来的request util等
  • store redux store
  • app.js 入口.js

containers 目录结构如下:

根据自己的业务,创建页面级别的组件

  • index.js 入口.js
  • .jsx 页面级别的组件
  • .less 页面级别的样式
  • components 这个页面独用的组件
  • flow 这个页面需要的action reducers

发布

使用 npm run build 构建待发布的资源,请忽略根目录中的index.html

建议发布规则:

  • 打包出来的dist发布到CDN中
  • 自己在服务端创建一个index.html,使用服务端输出的方式来引用一个version版本变量
  • 这个变量对应CDN的版本号

遗留问题

由于时间的原因,对于一些遗留的问题并没有处理好。

  • store 数据的清楚机制
  • 基于webpack的异步处理方案
  • 使用classname搞的css module
  • 路由钩子处理
  • eslint规则配置,目前只加了一个pre-commit

期待对于此感兴趣的朋友来提PR

如果有幸阅读到了此处,你对烹饪感兴趣的话推荐关注鄙人的《每周例行》。当然如果你想联系我,可以给我发送私信或关注我的微信公众号fed-talk。