当前位置: 首页 > 后端技术 > Node.js

如何设计npm包的开发发布流程

时间:2023-04-03 21:22:43 Node.js

最近把一个公司内部使用的库发布到内网的npm私服上。直接发布比较简单,但是这个库是多人维护的。而且npm私服只有一套,所以生产环境和开发环境用的是同一套。那么,我们的需求就来了:如何设计npm包的开发流程和自动发布流程。这套流程我们要实现以下目标来支持团队合作。如果有代码的开发和提交,其他人可以及时同步到最新的代码。它可以支持定期迭代和修补程序。它是一致的自动发布,减少了手动操作。先说说如何搭建npm私服,如何发包,但这不是我们文章的重点,所以简单介绍下目前主流的npm私服搭建。它更轻便,符合我们的需求,所以我们选择它。Verdaccio搭建非常简单,使用默认配置即可,npminstall-gverdacciooryarnglobaladdverdaccioverdaccio即可,私服搭建完成。npm包发布有私服,我们先注册到本地npmnpmsetregistryhttp://localhost:4873然后添加用户,如果是第一次,会创建一个新用户npmadduser--registryhttp://localhost:4873最后发布npmpublish设置版本号有两种方式,一种是手动修改package.json中的版本//package.json{"name":"project","version":"1.0.0",}另一种是通过npmversion修改版本号,它提供了如下参数npmversion[|专业|未成年人|补丁|预科|初级|预补丁|预发布[--preid=]|from-git]详细解释如下:newversion:自定义版本号,除了已经发布的版本号,随便写什么major:升级主版本号1.0.0->2.0.0minor:upgradetheminorversionnumber1.0.0->1.1.0patch:Upgradepatchnumber1.0.0->1.0.1premajor:准备大版本preminor:准备小版本prerelease:预发布版本执行npmversion后,一个会生成新的提交记录,比如执行npmversion2.0.0完成后查看日志,会发现commitmessage,commitmessage为2.0.0。为什么会产生这条记录?很简单,因为npmversion命令其实就是修改package.json中的版本,修改后提交,所以就有了这条新的提交记录。如果想自定义提交记录,可以写npmversion2.0.0-m"Upgradeto%sforreasons"其中%s是修改后的版本号。gitlabCI我们计划使用gitlabCI实现自动发布,同时也简单介绍一下gitlabCI的一些步骤和配置项。该项目启动CI并选择一个公共运行器。如果没有,你只能自己弄一个。在项目根目录新建.gitlab-ci.yml,写入配置。详细配置请参考gtilab官网来,我画图给大家介绍一下我们的设计思路。我们先设置一些约定分支的约定项目的分支计划,设置三个分支feature分支:常规功能迭代master分支:stable分支hotfix分支:当有紧急修改时,创建这个分支作为临时修复分支,所以采用不影响正常功能的开发版本号约定。我们使用majorversion:minorversion:次版本号的方式。特性分支上的每次提交都会触发版本号升级。比如当前feature分支的版本号是1.1.5,那么下一次提交会升级到1.1.6并发布npm。小版本号会按照常规要求迭代升级。No.升级到1.2.0并发布npm。大家发现1.1.8和1.2.0是一样的代码。是的,之所以会这样,是因为次要版本号对应一个周期的定期修改,所以升级后的1.2.0就是下一次定期要求的版本号。这样这个版本号就对应了每次提交,次版本号就对应了当前的开发阶段。这两者都可以由CI触发。不需要人工参与,还有一个大版本号,只有在大改版的时候才手动修改。一般来说,升级大版本号的频率比较低,手动修改完全OK。你会发现每次commit都要触发npmversionpatch&npmpublish感觉太频繁了,但是为了满足团队协作,不得不做出一些小的让步。所以这里这个版本号的作用不是区分版本,而是真正用来区分版本的是次版本号,所以在引用这个npm的时候,需要这样控制版本号,例如“my-package":"~1.2.0"锁定了主版本号和次版本号,无论我们在开发过程中提交多少次,我们的引用总是最新的。时序图绘制开发和发布的时序图,如下。开发流程时序图如下发布流程时序图编码实现主要是CI编码,如下#.gitlab-ci.yml#definestagesstages:-publish#definejobjob2:stage:publishbefore_script:-cd/home/node/MY#进入项目目录-gitcheckout.-gitcheckout$CI_COMMIT_REF_NAME||gitcheckout-b$CI_COMMIT_REF_NAME-gitpull-f-Xtheirsorigin$CI_COMMIT_REF_NAME-纱线脚本:-nodepublish.js//publish.jsvarshell=require('shelljs');vargit=require('git-last-commit');varfeatureBranchName='feature-npm';//判断文本是否为版本号格式functioncheckCommitMessage(subject){return/^\d+.\d+.\d+$/g.test(subject)}//获取最新的commit,判断是否为版本号格式,如果不是则发布,git.getLastCommit(function(err,commit){console.log(commit);const{subject,sanitizedSubject}=commit;shell.exec('echo$CI_COMMIT_REF_NAME');if(!checkCommitMessage(subject)){if(sanitizedSubject.indexOf(`Merge-branch-${featureBranchName}-into-master`)>-1){shell.exec('gitcheckout.');shell.exec(`gitcheckout出${featureBranchName}||gitcheckout-b${featureBranchName}`);shell.exec(`gitpull-f-Xtheirsorigin${featureBranchName}`);shell.exec('npm版本次要');shell.exec('npmpublish');shell.exec(`gitpushorigin${featureBranchName}`);}else{shell.exec('npm版本补丁');shell.exec('npm发布');壳。exec('gitpushorigin$CI_COMMIT_REF_NAME');}}});//package.json"scripts":{"test":"echo\"Error:notestspecified\"&&exit1","prepublish":"buildscript"},有个函数checkCommitMessage在release脚本中判断最新的提交消息是否为版本号格式,因为最后我们会有一个push操作,push之后会再次触发CI,所以为了防止死循环,我们使用提交的消息作为触发CI的基础。这样,我们就需要规范消息的格式。我的建议是遵循这种格式U${modifiedspecificcontent}。总结此解决方案不是通用解决方案。毕竟每个团队的开发流程都不一样,目前的方案适合我们现在的场景。如果有和我们场景一样的朋友,可以试试看。如果你有更好的解决方案,请分享给我们~