自动化重构 - jscodeshift

自动化重构(jscodeshift) 在这篇文章里我想要通过一些小例子来介绍使用jscodeshift来进行自动化重构的技术。具体来说,我想要介绍在一个组件库的开发和维护过程中,如何使用jscodeshift来自动修改公开的API接口,从而尽可能小的产生对组件用户的影响。 如果你们团队开发的组件被其消费者(组织内部或者外部)使用了,而这些代码又不在你的控制之内,那么这里讨论的技术和模式可能对你很有帮助。而如果你的日常工作更多的是使用组件库来开发应用程序,我希望这里的知识和技巧仍然对你有所启发,毕竟在软件系统中,我们往往都既是某些库的消费者,又同时是另外一些库的生产者。 从一个简单场景出发 设想这样一个场景,你发布了一个酷炫的组件库(fancylib),其中有一个按钮(Button)组件。这个Button的一个属性是当点击后处于加载中(loading)状态时现实一个表示加载中的小图标。 (图片来源:https://xd.adobe.com/ideas/process/ui-design/designing-interactive-buttons-states/) 在代码实现中,这个加载中状态被定义为了名为isInLoadingStatus公开prop。用户可以通过设置其值来控制Button的状态: import Button from '@fancylib/button'; const app = () => ( <Button isInLoadingStatus>Click me</Button> ) 一个实习生在某一天code review的时候提出了一个问题:在组件库中的其他地方,所有的boolean状态都是用一个单词来表示的,比如checked, disabled等。如果按照这个惯例,这里应该把isInLoadingStatus简化为loading。好主意! import Button from '@fancylib/button'; const app = () => ( <Button loading>Click me</Button> ) 假如所有用到Button的地方都在你的控制之内,字符串替换大约是一个快速且80%有效的方案。不过稍微分析一下,你就会发现简单的Shift+F6会遇到很多问题。 复杂情况 比如用户对其做了二次包装以适配更符合自己用户的使用习惯,这使得简单的全局字符串替换变成了不可能:: import Button as FancyButton from '@fancylib/button'; const MyEvenFancierButton = (props: FancyButtonProps) => ( const theme = { backgroundColor: "orangered", color: "white" }; <FancyButton {...props} theme={theme}>Click me</FancyButton> ); 除了这些问题之外,由于这是一个非常受欢迎的组件库,Button在很多(包括内部和外部的)产品中都有使用,你没有办法访问所有的用户代码,更没有办法让所有人都用手工的查找替换来做更新,你需要另寻出路。 你需要一个工具 – 一个可以读懂代码意图的工具 – 来帮助你做修改,而且整个过程最好可以自动化,比如通过执行一个脚本来完成。...

December 11, 2020 2 min