更新:
做完没多久CRA居然更新4.0了,导致一些功能不能用了不说,居然不支持在tsconfig里加path了……好在11月23号他们发布了react-scripts 4.0.1解决了这个问题,不然我已经打算用fork react-scripts的路子了。4.0更新后主要是customize-cra这个包的功能有一些不好用了,所以我干脆干掉了这个包,直接修改webpack的配置,也把所有babel相关的都放到了.babelrc里,功能上和之前的版本一致,开始支持React 17.X。
FB官方的React项目手脚架create-react-app(以下简称CRA)一直被广泛使用,但是CRA的定制性并不好,很多实际开发中的需求都需要将react-script eject才能解决,不过这样就变成了完全自己维护的CLI,不容易帮助到后面的项目复用。React官方还提出过fork react-script的方法,但本质上也是需要自己维护的类CLI工具,个人感觉并不是一个很好的解决方案。在react-scripts@3.3.0以后,CRA增加了自定义模板的功能,我个人用下来感觉比较好的解决了复用CRA自定义功能的问题。
官方文档:Custom Templates | Create React App
模版可以用来进行项目初始化,包括必要的生态整合,工程化的目录结构,编码辅助工具等,因为是CRA的模版,所以继承了CRA的所有能力,包括变量配置、代理等。对于人力有限的团队来说,比开发一个CLI的成本小了不少,还能有持续更新的能力。使用模板进行CRA初始化,大量的模版文件不在需要从别的项目复制粘贴过来,也可以通过模版快速复用已有项目的能力。
代码地址:cra-template-jw-mst
使用方式
npm包
npx create-react-app my-app --template [template-name]
本地文件
npx create-react-app my-app --template file:../path/to/your/template/cra-template-[template-name]
下面介绍一下我个人开发的一个模版,主要为了实现两个方面的能力:
生态整合
首先是整合React项目中必要的生态组件,这样通过模版新建的CRA项目就不再需要手动安装大量必要的依赖包,还可以统一不同项目中的技术栈。我选择整合的主要是Router、数据管理、以及API请求工具这几个必须的东西。组件库我没有增加,这样不同的项目可以灵活的选择,提高了模板的通用性。
React Router
选择了分布式路由理念的React Router v5,路由即组件,内部子路由使用进行声明,支持Hooks API。history方式采用broswer history,还与mobx model进行连接。
Mobx + Mobx State Tree(MST)+ Mobx React
数据管理方面我根据个人经验选择了Mobx + Mobx State Tree(MST)的组合。国内用Mobx的比较多,使用MST的人很少,资料也不多,一些人尝试过之后觉得MST的写法太不灵活,相比Mobx好像没有增加什么功能,导致大部分人对此并不感冒。
我之前使用Mobx做过一个很大型的项目,遇到一些项目大了导致Mobx管理数据的问题,为此也尝试过Redux的解决方案,但是感觉Redux还是过于繁琐了。MST其实就是基于Mobx的Redux,只不过通过Mobx而不是通过props驱动React组件更新。MST可以直接使用Redux dev tools进行调试,并且整合了对异步action的处理,还支持Mobx的compute value,局部还可以直接使用Mobx替换React State,在大型项目上是一个不错的解决方案。 我的模版选择了单一全局的MST Model进行数据管理,Model通过React Context和Mobx React Provider的方式注入到组件中,保证所有组件都可以连接到全局的model。
Axios
模版对axios的默认API做了一层封装,统一了请求函数入参格式、通用请求参数等,而且方便后续增加拦截器
工程化
Typescript
这里顺应潮流,选择TS作为模版的语言。但是在tsconfig.json中关闭了严格模式,还增加了对webpack path alias的支持
目录结构
components
全局通用组件目录。这里的组件不关联数据管理,否则认为该组件不是通用组件而是业务组件。通用组件应包含单测及功能测试,防止修改后全局各处引用出现问题。
models
数据管理目录。存放全局的数据管理Model,Model中存放需要跨组件使用的数据,根据业务需要对数据模块进行拆分。
pages
业务组件目录,包括路由、页面、业务功能等。React项目中,路由、页面都是组件,页面和组成页面的组件与业务直接相关,与数据模块关联实现真正的业务功能,所以都是业务组件。
utils
工具函数目录。存放项目通用的工具函数,如api请求封装方法。
开发工具
Babel
模版增加了.babelrc文件,方便配置babel plugin,把所有babel相关的功能都放到了这个文件里。增加了jsx-control-statement plugin在JSX中编写<If><Choose><For>等条件tag。
Eslint
模版增加了.eslintrc文件,方便配置eslint,默认使用airbnb加prettier规则。
Prettier
模版增加了.prettierrc进行配置,运行npm run prettier命令可以对全局文件进行格式化。
Webpack配置自定义
CRA的Webpack配置有一些不合理的地方,不够灵活,还比较影响开发体验。这里通过react-app-rewired重写了一些webpack的配置,如:禁用eslint检查(新版本改用eslint webpack plugin,列改配置的路都封死了,干脆干掉)、使用.babelrc、增加webpack alias等等,位于config-overrides.js。
测试
测试框架没有改变,还是使用了CRA整合的jest,测试库从react-test-util换成了enzyme+jest-enzyme的组合,主要是感觉enzyme的配套生态更好一点,写测试的速度会更快,而且有更好的文档支持。