资讯专栏INFORMATION COLUMN

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

qieangel2013 / 2851人阅读

摘要:所以此版本号在这里的作用并不是用来区分版本的,小版本号才是真正用来做版本区分的,那么在引用这个就要这么来控制版本号,举个栗子锁定大版本号和小版本号,不管我们开发过程中提交了多少次,我们引用都是最新的。

最近在把公司内部用的一个库发布到内网的npm私服上,仅仅是发布的话是比较简单的,但这个库是由多个人一起维护的,而且npm私服只有一套,所以生产环境和开发环境,用的是同一个,那么,我们的需求来了:如何设计npm包的开发流程和自动化发布流程。 这一套流程我们想要的达成如下目标

支持团队协作,有开发提交代码,其他人能及时同步到最新代码

能够支持常规迭代和hotfix上线

同一版本开发、测试、生产环境的引用包的版本号都是一致的

自动化发布,减少人工操作

先说下如何搭建npm私服和如何发包,不过这不是我们这篇要讲的重点,所以我们就简单介绍

npm私服搭建

目前比较主流的有 nexusVerdaccio,因为 Verdaccio 要更轻量些,而且也满足我们的需求,所以我们选择它。 Verdaccio 搭建非常简单,直接使用默认配置就行

npm install -g verdaccio
or
yarn global add verdaccio
verdaccio

就这样,私服就搭建完成啦。

npm包发布

有了私服,我们先注册到本地的npm中
npm set registry http://localhost:4873
然后添加用户,如果是首次,则会新建用户
npm adduser --registry http://localhost:4873
最后是发布
npm publish

设定版本号有两种方式,一种是人工修改 package.json 中的 version

// package.json
{
  "name": "project",
  "version": "1.0.0",
}

另一种是通过 npm version 来修改版本号,提供有这如下参数

npm version [ | major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=] | from-git]

详细解释如下:

newversion:自定义版本号,除了已经发布的版本号,想写啥写啥
major:升级主版本号 1.0.0 -> 2.0.0
minor:升级次版本号 1.0.0 -> 1.1.0
patch:升级补丁号 1.0.0 -> 1.0.1  
premajor:预备主版本
preminor:预备次版本
prerelease:预发布版本

在执行npm version后,会产生一条新的提交记录,比如说执行 npm version 2.0.0完后 ,查看log,会发现一条 commit message 为 2.0.0 的提交记录,至于为啥会生成这条记录呢?很简单,因为npm version这行命令其实是修改了 package.json 中的 version ,修改后并提交,所以就有这条新的提交记录。要是想自定义提交记录,可以这么写 npm version 2.0.0 -m "Upgrade to %s for reasons" 其中%s就是修改后的版本号。

gitlab CI

我们打算使用 gitlab CI 来实现自动化发布,我们也简单介绍下 gitlab CI 的一些步骤和配置项。

项目开启CI,选择一个公共的 runner,要是没有,那就只能自己弄一个。

项目根目录新建 .gitlab-ci.yml,写入配置,详细的配置可以查看 gtilab官网

# 定义 stages
stages:
  - build

定义 job
job1:
  stage: build
  script:
    - echo "xxx"

配置完成

设计阶段

我们要说的重点来啦,通过画图的方式来给大家介绍我们的设计思路。先来设定些约定

分支的约定

项目的分支的规划,设定三个分支

feature分支:常规功能迭代

master分支:稳定分支

hotfix分支:当有紧急修改时,创建该分支,作为临时修复分支,这样可以不影响常规功能的开发

版本号的约定

我们采用 大版本:小版本:次版本号 这种方式,每一次feature分支上的每次提交都触发此版本号升级,比如当前feature分支的版本号是 1.1.5 那么下一次提交就会升级为 1.1.6 并发布npm,小版本号跟着常规需求迭代往上升级,比如说当前是 1.1.8 ,周期性的需求在明天上线,那么上线后,版本号就升级为 1.2.0 并发布npm,大家发现 1.1.81.2.0 是同样的代码,没错,之所以这么做是因为小版本号对应的是一个周期的常规修改,那么升级的 1.2.0 就是作为下一次的常规需求的版本号,这样一来,此版本号对应的是每一次提交,小版本号对应的是当前的开发阶段,这两个我们都可以通过CI来触发修改,不需要人工参与 ,剩下还有个大版本号,这个只有在大改版的情况下才由人工修改,一般来说升级大版本号的频率是比较低的,人工来来修改完全是OK的。

大家会发现每一次提交就触发 npm version patch & npm publish 感觉太频繁了,但为了能满足团队协作,只好做些小小的让步。所以此版本号在这里的作用并不是用来区分版本的,小版本号才是真正用来做版本区分的,那么在引用这个npm就要这么来控制版本号,举个栗子

"my-package": "~1.2.0"

锁定大版本号和小版本号,不管我们开发过程中提交了多少次,我们引用都是最新的。

时序图

画了开发、发布的时序图,如下。

开发流程时序图

开发时序图如下

发布流程时序图

编码实现

主要是CI的编码,如下

# .gitlab-ci.yml
# 定义 stages
stages:
  - publish

# 定义 job
job2:
  stage: publish
  before_script:
    - cd /home/node/MY #进到项目目录
    - git checkout .
    - git checkout $CI_COMMIT_REF_NAME || git checkout -b $CI_COMMIT_REF_NAME
    - git pull -f -X theirs origin $CI_COMMIT_REF_NAME
    - yarn
  script:
    - node publish.js
// publish.js
var shell = require("shelljs");
var git = require("git-last-commit");
var featureBranchName = "feature-npm";
// 判断文本是否是版本号格式
function checkCommitMessage(subject) {
    return /^d+.d+.d+$/g.test(subject)
}

// 获取最近一次提交,判断是否是版本号格式,若不是,则进行发布,
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("git checkout .");
            shell.exec(`git checkout ${featureBranchName} || git checkout -b ${featureBranchName}`);
            shell.exec(`git pull -f -X theirs origin ${featureBranchName}`);
            shell.exec("npm version minor");
            shell.exec("npm publish");
            shell.exec(`git push origin ${featureBranchName}`);
        } else {
            shell.exec("npm version patch");
            shell.exec("npm publish");
            shell.exec("git push origin $CI_COMMIT_REF_NAME");
        }
     }
});
// package.json
"scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "prepublish": "build script"
  },

发布脚本里有个函数 checkCommitMessage 用于判断最新的提交message是不是版本号格式,因为我们最后会有一步push的操作,push后会再一次触发CI,所以为了防止死循环,我们通过提交的message作为是否触发CI的依据,这么一来我们就要规范message的格式,我的建议是按照这个格式 U ${修改的具体的内容}

小结

这个方案不是个普适性的方案,毕竟每个团队的开发流程都不一样,目前这个方案是适合我们目前的场景的。如果有小伙伴的场景跟我们的一致,可以尝试下,如果小伙伴们有更好的方案,欢迎一起交流呀~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/103717.html

相关文章

  • 减小发布npm包的体积与避免重复依赖

    摘要:我们可以把未经过打包的源代码发布到,并把中的字段指向源代码,这样引入的就交由项目的构建工具来进行处理,因此理论上就可以避免重复依赖了。总结通过这两天的折腾,主要收获有点发布包的流程中的字段判断重复依赖的机制基于组件封装组件时如何避免重复依赖 这两天一直在忙于封装一个vue table组件并发布到npm,记录一下我是如何把npm包的大小从100多kb减小到不足1kb的过程。 背景 这个组...

    xiaotianyi 评论0 收藏0
  • 前端每周清单第 47 期:NPM 年度报告与 2018 展望,Airbnb React Router

    摘要:确定新的包命名规则为了尽可能避免包的误植域名现象,将不会再允许使用相似的包命名不过会进一步鼓励开发者使用自己的命名空间来发布包。本文是对其几十年来技术之路的回顾与展望,也是一代技术人的青春回忆。 showImg(https://segmentfault.com/img/remote/1460000012846628); 前端每周清单专注前端领域内容,以对外文资料的搜集为主,帮助开发者了...

    makeFoxPlay 评论0 收藏0
  • 如何发布你自己的React模块至NPM

    摘要:文章介绍如何创建发布一个包,包括项目搭建发布流程注意事项等。语义化版本号分为三位。主版本号当进行了大都改动或者对有很多不兼容修改时应该进行版本号升级。次版本号增加了部分特性或者优化时升级该版本。如如果你想撤回指定版本,执行包名版本号。 文章介绍如何创建发布一个npm包,包括项目搭建、发布流程、注意事项等。 演示代码GitHub地址 1. 初始化项目 首先在创建好的项目文件夹下面执行 ...

    zombieda 评论0 收藏0
  • 发布 react 组件到 npm

    摘要:我发布了我的第一个组件,一个基于的标签云组件。然后将这个编译命令写到里,如下那么以后要编译下面的代码,只需要执行现在我们已经有编译好的代码了,接下来就可以发布到供其他人使用了。 我发布了我的第一个 npm 组件,一个基于 react 的 3d 标签云组件。在这途中我也是遇到了很多的坑,花在完善整个发布流程的时间远多于写这个组件本身的时间,所以我记录下我觉得一个正常的 react 组件的...

    Yi_Zhi_Yu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<