路漫漫其修远兮,吾将上下而求索。
背景
完全是出于实践的目的,在一个小业务中,将最新的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。