本文首发于我的个人博客
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
在 npm 包开发及发布中,或多或少都会遇到一些问题。在此,我将本人一些经验分享给大家。
开发前准备
如何选择开源许可?
开发并发布一个 public npm package ,就代表将相关代码进行开源,那这个时候代码的开源许可就是第一步。
对于一些常用开源许可及其约束,可参考各种开源协议介绍 以及 Open Source Initiative 。
以我的经验来说,严格一点的限制就是 GPL ,宽松一点的就是 MIT。
GPL 代表代码及代码衍生品必须是开源的。MIT 代表代码的衍生品或代码本身可以被销售、闭源。
我个人采用的都是 MIT 协议。
对开发及发布目录的设定
npm 的开发和发布目录可以是两个分开,也可以是共用一个。
一般两个分开的是使用 ts 开发,使用 tsc 进行编译。或者开发后使用 webpack 之类的编译工具进行混淆编译或压缩。这时候就会存在两个目录,源代码目录(一般是 src )和编译后代码目录(一般是 lib )。
如果共用一个,则代表代码不需要编译,直接发布。
在对目录进行设定时,需要注意 package.json 中的 main 和 types 以及 files 字段。main 代表着 js 环境下的工程入口,types 代表着 ts 环境下 声明文件入口, files 代表需要发布的文件。
在一般不太规范的项目中,这两个字段即使配置错了,也无伤大雅。因为启动时都是直接从工程入口启动。但是如果你的工程是一个 npm 包,需要被他人引用的情况下,这里就需要注意了。
如果你是编译后发布的话,main 和 types 这两个字段代表着是你编译后目录下的工程入口。如果是不编译直接发布,这两个字段代表着你源代码的工程入口。
如果不配置好这三个字段的话,则可能会出现以下问题:
- 发布了 npm 包,结果安装后发现里面是空的。(files 没配置好)
- 发布了 npm 包,结果安装后发现里面有文件,但是引用不到。(main 和 typs 没有配置好)
{
"main": "lib/index.js",
"types": "lib/index.d.ts",
"files": [
"lib/*"
]
}
复制代码
版本管理
npm 的版本管理有以下特点:
- 默认不可重复发布相同的 version,但是可以在发布时设置。
- 使用 semver 版本规范。
- 发布某一版本后,可以在符合 npm 规定的条件下进行撤销此版本。
在发布版本时不建议通过在版本号后面加 -alpha 这样的方式来标明预发布版本,可以通过使用 preid 的方式来实现指定预发布版本。
在发布版本时,很多小伙伴可能会有一个初始版本的困惑。即,我的第一个版本应该是多少?
我的个人建议是 0.0.0
,从 semver 规范 来说,推荐使用 0.1.0
,但是我认为 0.1.0
其实代表已经开发出一部分功能了,如果从 0.1.0
开始,则代表从已经拥有部分功能的基础上开发,这样相当于我开发了一个版本,但是已经有两个版本了。但是一开始我们是一穷二白的,0.0.0
可以不视为一个版本号,可以将开发完一部分功能后的第一个版本定为 0.1.0
,而不是将初始版本定为 0.1.0
。
包括从 0.y.z
切换为 1.y.z
,可以不一定按照官方说的正式版本必须是 1.y.z
,axios 到目前为止也都是 0.y.z
,这一块也是见仁见智,只要在文档中说明你目前的版本状态即可。
当然,以上只是个人建议。
Script
package.json 的 script 是一个非常强大的工具字段。你可以在里面去配置每次 publish、commit 前要做的操作,比如检查代码,格式化代码、运行测试用例等等。通过这样的手段来确保你提交的是一份质量较高的代码。
在发布、编译、更改版本前后的 hook,可以参考 npm 的生命周期。如果是需要在 commit 前进行自动化操作,可以通过安装 pre-commit 来实现。
私有包 和 scope 包
如果你想发布的是一个私有包,在公司或组织内部使用的话,你可以发布私有包。
私有包有几种发布方式:
- 开通 npm 付费账号。
- 搭建内网 npm 私有仓库,推荐 cnpmjs。
- 使用 git 私有仓库,推荐 gitea,可能存在的问题参考。
如果你是一名有钱银,开通了 npm 付费账号,可以通过发布 发布 scope 包,发布为私有包。
开发中
完成了上面几个操作,就可以愉快的敲代码了。
开发中基本没什么坑,即使有坑,一般都是对 js 特性了解不全。
开发后
开发后就是需要做一些比较痛苦,比如:
编译
如果使用 ts 开发,使用 tsc 进行编译时,需要注意一个问题,如果你存在不直接引用的代码,需要在 tsconfig.json 中特别标明,如果你涉及到了自定义模版文件的处理,那你需要在编译后通过脚本或其他方式手动将文件 copy 过去。
文档
作为一个对外提供服务的包,你需要有一个比较详尽的文档。关于文档方面,我的做法如下:
-
每完成一个版本,完善当前版本相应的文档,包括但不限于:
- 整体包的介绍。
- 包的方法或类的具体名称、调用方式、作用等。
- 相关的代码示例。
-
文档的表现形式一般如下:
-
要想写好文档,README是重中之重,因为 README 代表的是一个项目的脸面,不管 github 还是 npm ,首先看到的都是 README。README 不规范,多半也没兴趣再深入了解。对于标准的 README 可以参考 standard-readme 。
当然,也不必完全照抄,可以加入一些自己的理解,根据项目实际情况做一些调整。比如我的这几个项目@eliassama/regex、npm-package-cli、comsvr-ast、comsvr-random。
测试
一个好的项目,将近 1/3 的时间都在测试。不过对于个人来说,虽然未必有这么严苛,但是基础的测试还是要的,总不能发布的代码都有问题,那别人还用个罗永浩?
测试建议采用自动测试,推荐使用 jest,并且配置好,每次编译后、commit 前、publish 前都执行下自动化测试,避免提交问题代码。
对于一些不方便测试的,比如 cli 工具,也要在改完后尽可能去测一下。
记住测试的时候,如果你存在编译后文件,一定要去引用编译后的文件去测试,这样你才会发现一些问题,比如部分文件没有编译进去等等。
打 tag
当你测试完没问题,文档也写完的情况下,不要忘记打个 tag,以此来标识你的一个稳定或预发布版本。
本文首发于我的个人博客。
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
发布
在正式发布前,你需要自己去核对以下问题:
- 当前的代码目录下是最新代码吗?(因为我双分支切换,dev 分支开发,main 分支进行打包发布,所以有时候切到 main 上会忘记pull。)
- 如果是第一次发包,请确定工程入口、包名、私有/公有属性、git url 地址、编译后目录内文件、版本号是否都是准确无误的。(别问我为啥说这个,你敢信我曾经连续发了三个版本没发对。。。)
- 如果你是多个账号,请确认发包账号是否是预期的。
- 检查下 readme 的错别字或者描述,发版后,不可能因为一个 readme 再搞一次的。
- 部分文件即使你指明了,也无法发布。如果你想将它们作为模版文件或其他原因必须发布的话,建议改名。参考npm publish 会忽略的文件。
当你走到这一步,就代表你已经正式的发布了一个版本,后续的维护和发版,只需要再次按照这些步骤操作就可以了。
我使用我自己开发的一个 cli 工具 npm-package-cli 初始化了一个 npm packag 模版仓库 npm-package-template。有兴趣的可以参考,或提出一些建议。