从0到1,搭建一个体系完善的前端React组件库

我们的技术栈涉及ReactWeb 与 React Native, 对于RN的代码,我们一般会走源码直接发布,RN项目中的编译过程会自动处理node_modules里的源文件。但是对于Web组件库而言,更传统的做法,则是需要在发布之前进行一些编译和转码,这样才能确保发布之后的npm包,可以在大多数环境下正常运行起来。

对于Web端组件库的打包,我们进行了多次的探索和优化。

使用webpack对每个组件进行单独打包,打包类型由umd改为commonjs2。

module.exports = {

output: {

filename: ‘[name].js’,

path: path.resolve(__dirname, ‘…’, ‘dist’),

library: ‘Tha’,

libraryTarget: ‘commonjs2’ // umd

}

}

通常我们对组件库的建议是umd打包,因为这样可以实现多种模块方案的加载通用性。但在实践过程中发现,每个组件都需要单独打包时,UMD的打包方式,会显著增大每个文件的基础体积;而且我们99% 的场景下,其实已经并不用再去兼容AMD、CMD等模块加载方式。

在确保我们的代码一定是通过node模块方式加载的时候,我们只需要打出commonjs2的模块即可。这一步的调整,显著地提升了打包速度,也明显减小了各个文件的打包体积。

进一步编译优化

对于组件库而言,使用webpack进行打包,即使是使用了commonjs2的模式,繁重的配置工具仍然是显得重了一些,而且需要额外配置各种external规则,以防止打包时打入了额外的第三方库的代码。使用rollup来处理组件库的打包固然比webpack要合适,但是又会额外引入新的构建工具,增加学习成本。

最终我们选择的更优化的方案,是使用babel 直接做编译转换,不使用任何额外的构建工具,也不做压缩优化处理---- 这些工作,在现代化的前端项目中,都会自动处理,不需要组件库再做多余的构建动作。Babel直接转码的方式,帮助我们省去了很多复杂的配置工作,并且让组件库打出来的生产代码更加容易调试。

优化前,使用webpack等构建工具打包组件:

{

“scripts”: {

“build:components”: “webpack --config ./build/webpack.config.js --color”,

“build”: “npm run build:components && npm run build:css && npm run copy_package”

}

}

优化后, 编写脚本直接对组件源文件转码

{

“scripts”: {

“build:components”: “cross-env NODE_ENV=production node ./build/trans”

}

}

提取组件中的样式文件,单独打包

Css-in-js的开发方式固然是方便许多,但是在打正式包时,内嵌的css实际会占用更多的代码体积,并且node_modules里的js代码中如果有显式require css的语句时,在同构项目中,可能会遇到服务端解析css文件的各种问题。

为了解决这个问题,我们提取了所有组件的css进行单独打包。其中所有的基础组件样式,会整体打包成一个main.css;而复杂业务组件的样式,则会以组件为单位进行单独打包,以便实现后续流程中业务组件的按需加载。

三、组件库实现业务组件的按需加载

与各大知名的开源组件库类似,为了减少项目的打包体积,我们对组件库中的复杂业务组件,如航班组件、机场组件、城市选择组件等,设计了按需加载的模式。

对RN而言,我们直接利用了require的特性,通过修改导出对象的get方法,显式地声明了lazyLoad的组件程式。

module.exports = {

//按需动态加载的模块

get AddressList() { return require(‘./Address/List’).default; }

};

对于Web而言,我们采用了类似ant-design的方式,在前面对业务组件的css进行单独打包处理后,通过在项目中引入babel插件的方式,实现组件的按需加载。

import { Address } from ‘@ctrip/thanos-ctrip-mobile/components.biz’

/*

  • 等价于

import Address from ‘@ctrip/thanos-ctrip-mobile/components.biz/Address’

import ‘@ctrip/thanos-ctrip-mobile/components.biz/Address/style.css’

*/

四、解决组件库日渐臃肿问题

随着组件库的不断迭代,组件代码会不断增多,需求也会越来越复杂。其他研发同学也可能会开发独立的npm组件包,但是会基于已开发完成的组件库的部分功能来实现。

这种情况下,开发其他npm包的同学,可能只想使用当前已有库中的部分功能,而不太愿意引入一个完整而庞大的组件库。为了使组件库的功能更加独立且通用,让UI组件与功能模块之间更好地解耦,我们需要对组件库进行拆子包处理。

如组件项目中基础UI部分,从组件库中剥离,拆分成独立的ui-basic组件库;组件项目中工具方法(表单校验、环境判断、正则处理、时间日期格式化等),拆分成独立的 util库。这种拆分组件包的开发形式,组件库不再是所有功能都揉在一个仓库中,开发和维护将变得更加灵活且易于扩展。

拆包前,core的部分将随着功能的增加而越来越臃肿:

拆包后的结构:

如图所示,拆分独立功能包后,可以让我们扩展和组合出更多灵活多样的组件库,让组件库不再单一而臃肿。

五、解决子组件包的开发环境问题

拆分子组件包后,给组件库的多样性扩展带来了极大的便利,但随之而来的问题便是,每一个子组件包都需要单独维护,在开发子组件包时,每一个包都需要一个可运行的本地开发环境。

随着子组件包的数量逐渐增多,给每一个包都单独设立一个开发环境,必然会带来更大的维护成本。我们目前选择的解决方案是,对于粒度更细的子组件包,所有的子包会公用一套dev的开发仓库,通过 git modules在开发仓库中嵌套子模块仓库,实现了只维护一套开发环境,产出多个子模块包的组件库工厂。

在这种环境下,还可以做到当子模块之间存在相互依赖时,可以直接引用相对路径下其他模块的源码,不必为了调试某个模块的代码,而跑到node_modules里去翻找,徒增调试难度。

六、组件库文档化与协同开发

为了让组件库的开发流程更加规范,减少接入方的沟通成本,对组件库进行适当的文档梳理是十分必要的,我们使用gitbook 编写组件库的文档,并部署到公司内部的books平台上。同样借助于gitlab强大的web hook的能力,实现了文档仓库的自动更新与发布。

与此同时,我们也启用了协同开发的模式,让组件库成为一个内部的开源库,用车产线的研发同学,可以通过提交issuse和merge request的方式,自行对组件库中的个别需求进行开发,提升开发效率。

七、组件库单元测试、自动化与持续集成

单元测试

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 22
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值