导读
17年初,金融前端项目开始逐步大规模转向react技术栈。在完整经过第一个react项目的搭建、开发、上线后,积累了react项目运行必要的配置、使用方式、最佳实践等,这些为后续项目的迁移提供了参考。
背景
起初团队内新的react项目的搭建都是通过手动拷贝其他项目完成的,例如需要拷贝webpack配置、代码基本结构、组织方式、package.json等。这样虽然可以创建新的项目,但容易出现以下问题:
为了解决以上痛点,迫切需要推出两个工具:
一个自动化创建项目的工具,一键生成需要的项目模版,免去开发人员在项目之间来回拷贝;
一个通用打包脚本,将项目配置这种与业务无关的逻辑提取出一个通用npm包,使用时安装即可,开发同学可以无需关注配置细节、打包细节即可快速运行项目。
前期准备
为了开发出更贴合团队需求的工具,需要从以下几个方面考虑:
1、根据团队现有的项目类型,划分不同的项目模版,为开发项目脚手架作准备,提升开发效率、质量
开发脚手架的第一步就是要明确需要支持哪些项目,因为我们做的是多个不同的项目集合,需要充分了解团队内的项目结构,合理划分。如m端项目、pc项目,这两个方向的项目可以分别划分为两个模版,因为不同平台的页面需要的基础库不同、开发结构也不同;
2、提取项目通用配置,高度抽象不同项目间的配置差异,为开发打包脚本做准备,提升开发体验
架构及实现
脚手架
提到脚手架,我们自然想到了yeoman生态系统。Yeoman是一个帮助开发者快速创建新项目的工具,通过开发yeoman的插件,即可在终端上使用 yo + 插件名 命令为用户生产文件。
可以实现如下功能:
因此,分离项目中的业务代码,最终提供可以运行起来的项目模版便成了首要开发目标。
该脚手架创建至今,已由最初的几个react项目模版增加了多个项目,如 node项目、小程序项目等。不仅仅是项目模版,除此之外每个项目内都包含了基础开发的最佳实践,以供开发同学参考。
其中,react相关的项目和组件都分别内置了我们的earth-scripts和earth-components-scripts打包脚本(后面会详细介绍),为项目提供统一的开发、打包配置。
脚手架生成项目流程
实现过程
开发者可以继承yeoman-generator,通过实现提供的生命周期钩子函数,来实现自己的插件。
接下来会详细介绍react项目打包脚本(earth-scripts)的实现方式。(earth-components-scripts与项目打包脚本类似,这里不再赘述)
react项目打包脚本
由于团队内使用react项目开发、打包的配置大同小异,在第一个react项目成功上线后,将其配置抽取出npm包。在充分了解团队内多个项目之间的差异及配置需求后,封装通用逻辑,并开放部分配置以满足项目定制化需求。
初版的配置功能主要如下:
但在实际使用中发现,仅仅是完成项目中的webpack配置已经远远不够,为了丰富脚本内容,提升开发体验,因此在社区内寻找优秀的框架。恰好当时react官方发布了create-react-App这个一键生成react项目的工具,通过查看create-react-app eject后的项目配置( 0.3.x 版本),发现其已经提供非常丰富的功能,正好弥补我们开发的不足,如:
开发环境下代码出错时提供友好的提示信息;
可视化展示build后的资源大小以及与上次build后资源大小的对比;
格式化webpack输出的资源信息;
清空终端console信息;
接口代理配置和webpack-dev-server的结合;
最终我们考虑将现有配置和react官方提供的脚本融合,提取出一套适用于金融前端团队使用的react打包脚本。除包含以上基本功能外,提供了如下能力(主要):
更多内容详见 https://www.npmjs.com/package/earth-scripts
由于积极跟进社区变化并及时更新,不断调整配置、使用体验、丰富功能,目前,该脚本已进行了3个重要大版本更新,100+次历史小版本迭代,已满足目前团队内所有项目的打包需求。
1、支持多页应用
项目的应用场景是多个或一个单页应用,为此,规定了项目src下的文件结构,兼容多页和原有的单页模式打包。
打包时读取src下的文件结构,如果无pages,则使用单页模式,如果有pages,并且和html的模版文件一致,则使用多页模式打包。将对应文件夹下的index作为入口文件,多页面即多个入口,动态配置webpack入口文件,同时使用html-webpack-plugin创建多个插件实例生成对应的html
2、分包优化
在升级至webpack4后,webpack本身提供了默认分包策略,同时我们也自定义了splitChunks的配置,并配置了分包优先级,最大化利用缓存。
提供分包配置入口,业务可自行决定将某些module在打包时打到vendor工具包中。
不建议将所有的node_modules下的包都打到一个文件里,因为除基础库外也有我们的组件包,组件是有一定的更新频率的,当组件更新了,这个工具包又会重新打包,生成新的chunkhash,这样就失去了缓存的意义。
因此,拆分出common和vendor两个包,业务代码和基础工具包分离:
3、开发环境下browserRouter支持
为了在开发环境也可以使用html5的browserRouter,在webpack-dev-server中对页面路径做了重定向。
在检测到一级路由是项目中pages文件夹下对应的路径,如/pages/user,当访问http://localhost:3000/user.html或者http://localhost:3000/user/xx时则直接返回对应的html,例如,在本例子中为user.html。
4、外链资源自动插入到html中,并与externals配置结合
在开发中,我们发现,一些高频基础库单独引用cdn的配置,既提升了打包速度,又可以合理利用cdn的资源。
扩展webpack配置使用方式
通过开发webpack插件,将配置中的entry动态插入html中
a) 将自定义配置项与webpack配置结合;
b) 读取配置中的entry,files字段,在插件中将entry中的资源配置到对应的files上。
5、不同类型资源使用不同的cdn路径
由于webpack的publicPath配置后,所有静态资源的路径都为当前配置的publicPath。为了满足不同资源有不同的cdn配置,所以通过插件修改:
a)通过html-webpack-plugin的暴露出的hooks事件(beforeAssetTagGeneration),对assets.js,assets.css的路径重写;
b) 由于在webpack打包后,js文件的加载路径是通过__webpack_require__.p拼接的 ,因此修改其值为js cdn的路径。
6、扩展的功能插件
目前团队内扩展了多个插件,用于对项目功能的扩展:
总结
脚手架及打包脚本已推广至金融前端部门所有项目使用,目前使用的项目有260+,组件55+。
提升了前端团队开发效率,带来以下好处:
后续仍会持续关注业内其他优秀的解决方案,不断优化,使开发更高效、提升开发质量。
参考文献:
https://www.npmjs.com/package/react-scripts/v/0.2.2
https://github.com/webpack/webpack/releases/tag/v4.42.1
作者简介:
坑红艳,金融公司前端技术部开发工程师,负责金融支付和基础平台前端开发。