26

58金融前端脚手架的设计与实现

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzI1NDc5MzIxMw%3D%3D&%3Bmid=2247490095&%3Bidx=1&%3Bsn=a806229eaa2e40d5b372f5d26e6bc97e
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

导读

17年初,金融前端项目开始逐步大规模转向react技术栈。在完整经过第一个react项目的搭建、开发、上线后,积累了react项目运行必要的配置、使用方式、最佳实践等,这些为后续项目的迁移提供了参考。

背景

起初团队内新的react项目的搭建都是通过手动拷贝其他项目完成的,例如需要拷贝webpack配置、代码基本结构、组织方式、package.json等。这样虽然可以创建新的项目,但容易出现以下问题:

  • 人工操作,在拷贝的过程中容易出现遗漏或者是误修改;

  • 开发人员既需要进行业务开发,也需要关注项目的配置,增加了开发成本;

  • 不同项目有自己定制的部分,团队人员之间接手项目也需要熟悉一遍配置流程,无法迅速的进入业务开发;

  • 项目基础包不同,开发人员需要频繁切换环境,增加了迁移成本。

为了解决以上痛点 ,迫切需要推出两个工具:

一个自动化创建项目的工具, 一键生成需要的项目模版, 免去开发人员在项目之间来回拷贝;

一个通用打包脚本,将项目配置这种与业务无关的逻辑提取出一个通用npm包,使用时安装即可,开发同学可以无需关注配置细节、打包细节即可快速运行项目。

前期准备

为了开发出更贴合团队需求的工具,需要从以下几个方面考虑:

1、根据团队现有的项目类型,划分不同的项目模版,为 开发项目脚手架 作准备,提升开发效率、质量

  • 确定项目类型

开发脚手架的第一步就是要明确需要支持哪些项目,因为我们做的是多个不同的项目集合,需要充分了解团队内的项目结构,合理划分。如 m 端项目、 pc 项目,这两个方向的项目可以分别划分为两个模版,因为不同平台的页面需要的基础库不同、开发结构也不同;

  • 项目模版的可扩展性。需要考虑后续可能会增加多种项目模版,方便模版的扩展;

  • 技术栈基础库版本统一,如react、react-router。合理约束基础库的版本,降低项目迁移时的人员学习成本。

2、提取项目通用配置,高度抽象不同项目间的配置差异,为开发打包脚本做准备,提升开发体验

  • 统一项目打包基础库,如webpack、babel

  • 提供个性化配置入口以满足不同业务需求

  • 方便接入,项目运行零配置

  • 与部署平台低耦合, 可以快速对接集团以及金融内部的部署平台。

架构及实现

脚手架

提到脚手架,我们自然想到了yeoman生态系统。Yeoman是一个帮助开发者快速创建新项目的工具,通过开发yeoman的插件,即可在终端上使用 yo + 插件名 命令为用户生产文件。

可以实现如下功能:

  • 根据用户的输入选择对应的模版文件

  • 拷贝模版文件到目标目录

  • 安装依赖

因此,分离项目中的业务代码,最终提供可以运行起来的项目模版便成了首要开发目标。

该脚手架创建至今,已由最初的几个react项目模版增加了多个项目,如 node项目、小程序项目等。不仅仅是项目模版,除此之外每个项目内都包含了基础开发的最佳实践,以供开发同学参考。

其中,react相关的项目和组件都分别内置了我们的earth-scripts和earth-components-scripts打包脚本(后面会详细介绍),为项目提供统一的开发、打包配置。

7zINNj2.png!mobile

脚手架生成项目流程

实现过程

开发者可以继承yeoman-generator,通过实现提供的生命周期钩子函数,来实现自己的插件。

3QfIbq7.png!mobile

接下来会详细介绍react项目打包脚本(earth-scripts)的实现方式。(earth-components-scripts与项目打包脚本类似,这里不再赘述)

react项目打包脚本

由于团队内使用 react 项目开发、打包的配置大同小异,在第一个react项目成功上线后,将其配置抽取出npm包。在充分了解团队内多个项目之间的差异及配置需求后,封装通用逻辑,并开放部分配置以满足项目定制化需求。

初版的配置功能主要如下:

  • 统一分包逻辑:runtime.js 项目启动文件、vendor.js 基础库包、入口文件chunk、异步加载chunk;

  • 仅支持单页应用;

  • webpack基础配置:dev环境下的hotReload;es6、scss等编译;build压缩等基本功能。

但在实际使用中发现,仅仅是完成项目中的webpack配置已经远远不够,为了丰富脚本内容,提升开发体验,因此在社区内寻找优秀的框架。恰好当时react官方发布了create-react-app这个一键生成react项目的工具,通过查看create-react-app eject后的项目配置(  0.3. x 版本),发现其已经提供非常丰富的功能,正好弥补我们开发的不足,如:

  • 开发环境下自动启动浏览器运行页面、端口号检测

  • react-dev-utils 提供多种插件和工具方法来提升开发体验:,比如:

开发环境下代码出错时提供友好的提示信息;

可视化展示build后的资源大小以及与上次build后资源大小的对比;

格式化webpack输出的资源信息;

清空终端console信息;

接口代理配置和webpack-dev-server的结合;       

  • 通过使用env配置来实现不同环境下的差异化配置

  • 单元测试Jest的基础配置及运行

  • ......

最终我们考虑将现有配置和react官方提供的脚本融合,提取出一套适用于金融前端团队使用的react打包脚本。 除包含以上基本功能外,提供了如下能力(主要):

  • 提供自定义config,开放部分webpack配置,如plugin、alias

  • 支持typescirpt

  • 支持多页

  • 分包优化

  • 开发环境下browserRouter支持

  • 外链资源自动插入到html中,并与externals配置结合

  • jest配置

  • 内置mock server

更多内容详见  https://www.npmjs.com/package/earth-scripts

由于积极跟进社区变化并及时更新,不断调整配置、使用体验、丰富功能,目前,该脚本已进行了 3个重要大版本更新100+次历史小版本迭代 ,已满足目前团队内所有项目的打包需求。

byeaUnN.png!mobile

实现过程

1 、支持多页应用

项目的应用场景是多个或一个单页应用,为此,规定了项目 src 下的文件结构,兼容多页和原有的单页模式打包。

VNb6Bf3.png!mobile

打包时读取src下的文件结构,如果无pages,则使用单页模式,如果有pages,并且和html的模版文件一致,则使用多页模式打包。将对应文件夹下的index作为入口文件,多页面即多个入口,动态配置webpack入口文件,同时使用html-webpack-plugin创建多个插件实例生成对应的html

2、分包优化

在升级至webpack4后,webpack本身提供了默认分包策略,同时我们也自定义了splitChunks的配置,并配置了分包优先级,最大化利用缓存。

提供分包配置入口,业务可自行决定将某些module在打包时打到vendor工具包中。

不建议将所有的node_modules下的包都打到一个文件里,因为除基础库外也有我们的组件包,组件是有一定的更新频率的,当组件更新了,这个工具包又会重新打包,生成新的chunkhash,这样就失去了缓存的意义。

因此,拆分出common和vendor两个包,业务代码和基础工具包分离:

jIJZ73e.png!mobile

3、开发环境下browserRouter支持

为了在开发环境也可以使用html5的browserRouter,在webpack-dev-server中对页面路径做了重定向。

在检测到一级路由是项目中pages文件夹下对应的路径,如/pages/user,当访问 http://localhost:3000/user.html 或者 http://localhost:3000/user/xx 时则直接返回对应的html,例如,在本例子中为user.html。

aeAfEbu.png!mobile

4、外链资源自动插入到html中,并与externals配置结合

在开发中,我们发现,一些高频基础库单独引用cdn的配置,既提升了打包速度,又可以合理利用cdn的资源。

VRnEJvU.png!mobile

扩展 webpack 配置使用方式

通过开发webpack插件,将配置中的entry动态插入html中

a) 将自定义配置项与webpack配置结合;

b) 读取配置中的entry,files字段,在插件中将entry中的资源配置到对应的files上。

6fIZ7bI.png!mobile

5、不同类型资源使用不同的cdn路径

由于webpack的publicPath配置后,所有静态资源的路径都为当前配置的publicPath。为了满足不同资源有不同的cdn配置,所以通过插件修改:

a)通过html-webpack-plugin的暴露出的hooks事件(beforeAssetTagGeneration),对assets.js,assets.css的路径重写;

b) 由于在webpack打包后,js文件的加载路径是通过__webpack_require__.p拼接的 ,因此修改其值为js cdn的路径。

6BnUjqI.png!mobile

6、扩展的功能插件

目前团队内扩展了多个插件,用于对项目功能的扩展:

  • service worker插件,提供PWA能力;

  • 错误捕获babel插件,为项目代码添加try-catch,并配合金融日志系统进行错误上报。

总结

脚手架及打包脚本已推广至金融前端部门所有项目使用,目前使用的项目有260+,组件55+。

提升了前端团队开发效率,带来以下好处:

  • 技术栈一致、基础类库一致;

  • 项目交接方便;

  • 高扩展性;

  • 快速创建项目,零配置运行,专注于业务开发。

后续仍会持续关注业内其他优秀的解决方案,不断优化,使开发更高效、提升开发质量。

参考文献:

https://www.npmjs.com/package/react-scripts/v/0.2.2

https://github.com/webpack/webpack/releases/tag/v4.42.1

作者简介:

坑红艳, 金融公司前端技术部开发工程师,负责金融支付和基础平台前端开发

#58技术1024活动开奖#

恭喜微信ID为风儿、莫名的青春、北巷的三位同学,获得100元京东E卡和58技术专属代码台历一本。

恭喜微信ID为宁夏、happy@one、唐、我有一头下毛驴呀,我从来也不骑、:balloon:、田优秀、意犹未尽的七位同学,获得58技术专属代码台历一本。

请以上获奖的同学,添加58技术小助手(jishu-58)领取奖品。

感谢大家的参与和支持,后续会有更多的活动推出,欢迎持续关注~

Nb2iMvQ.jpg!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK