如何发布一个 npm 包

lxf2023-04-08 13:26:01

我正在参与AdminJS会员专属活动-源码共读第一期,点击参与。

前言

npm(node package manager)作为 Node.js 的包管理工具,让世界各地的 JavaScript 开发者方便复用、分享代码以及造轮子;本文将介绍如何发布一个 npm 包,以及使用工具来自动化管理发布 npm 包;本文总览如下:

  1. 准备 npm 账号 & 示例包代码;
  2. 初始化 & 配置 package.json 文件;
  3. 确定发布的包版本
  4. 发布 npm 包;
  5. 使用 cli 工具 release-it 来自动管理版本、发布包等;
  6. 学习 npm init release-it 原理

准备

本地需要安装 Node.js 及 npm CLI,npm 将随 Node.js 一起安装,建议使用 Node 版本管理工具来安装 Node,例如 nvm 、n。

注册 npm 账号

第一步先到 npm 注册个账号 www.npmjs.com/signup,跟着注册步骤操作就行。

如何发布一个 npm 包

示例包代码

为了整个流程相对完整,创建个 github 仓库存放代码(本文代码仓库);将仓库克隆到本地后,新建 index.js 文件,这里我们随便搞点工具函数来作为示例。

// index.js  copy from @vue/shared
export const isArray = Array.isArray;
export const isMap = (val) => toTypeString(val) === "[object Map]";
export const isSet = (val) => toTypeString(val) === "[object Set]";
export const isDate = (val) => toTypeString(val) === "[object Date]";
export const isRegExp = (val) => toTypeString(val) === "[object RegExp]";
export const isFunction = (val) => typeof val === "function";
export const isString = (val) => typeof val === "string";
export const isSymbol = (val) => typeof val === "symbol";
export const isObject = (val) => val !== null && typeof val === "object";
export const toTypeString = (val) => Object.prototype.toString.call(val)

创建 & 配置 package.json

要发布一个 npm 包,需要创建一个 package.json 文件,用来描述包信息及依赖包。使用 npm init -y 命令创建一个默认的 package.json 文件,默认生成内容如下:

{
  "name": "utils", // 包名,必填且唯一
  "version": "1.0.0", // 版本号,必填,需遵循语义化版本规范
  "description": "", // 包描述信息,利于包检索
  "main": "index.js", // 入口文件,不设置默认为根文件夹下的 index.js
  "scripts": { // 脚本命令
    "test": "echo "Error: no test specified" && exit 1"
  },
  "repository": { // 项目代码仓库
    "type": "git",
    "url": "git+https://github.com/jizai1125/joker1125-utils.git"
  },
  "keywords": [], // 关键字,利于包检索
  "author": "", // 作者信息
  "license": "ISC", // 许可证协议
  "bugs": { // 问题反馈地址
    "url": "https://github.com/jizai1125/joker1125-utils/issues"
  },
  // 项目主页
  "homepage": "https://github.com/jizai1125/joker1125-utils#readme"
}

修改为如下,这里只填写了一些字段,根据项目需要配置。

{
  "name": "@joker1125/utils", // 这里为了避免包名冲突,加上命名空间 joker1125
  "version": "1.0.0",
  "description": "js utility functions", 
  "keywords": ["utils", "js-utils"],
  "main": "index.js",
  "author": "joker1125",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/jizai1125/joker1125-utils.git"
  },
  "author": "joker1125",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/jizai1125/joker1125-utils/issues"
  },
  "homepage": "https://github.com/jizai1125/joker1125-utils#readme"
}

要发布一个npm 包,name 和 version 字段是必填的;

包名(name 字段)命名规则:

  • 包名长度不能超过 214 个字符(命名空间也算在里面);
  • 包名所有字符必须小写;
  • 包名可以由连字符 - 组成;
  • 包名不能包含空格,不能以 . 或者 _ 开头,不能包含 ~)('!* 中的任意一个字符;
  • 包名不能包含任何非 url 安全字符(因为包名将作为 url 的一部分);
  • 包名不能与 Node.js / io.js 的核心模块、保留字或黑名单相同,例如 http

可以使用 validate-npm-package-name 包来检查包名是否合法

版本号(version 字段)则需要遵循 semver 规范。

可以使用 node-semver 来检查

扩展阅读:

  • npm Docs - package.json
  • New Package Moniker rules 译文 新的包名规则
  • semver 规范

确定版本号

填写好 package.json 字段后,接下来就是确定我们要发布的版本号,每次对包的更改都应该对应一个版本。

版本号格式

格式:MAJOR.MINOR.PATCH ,值非负整数,且禁止在数字前面补 0

  • MAJOR:主版本号
  • MINOR:次版本号
  • PATCH::修订号

版本号递增逻辑

  • 当有破坏性不兼容的 API 变更时,升级主版本号
  • 当新增一些功能特性时,升级次版本号
  • 当做一些 bug 修复时,升级修订号

当某个版本还不稳定的时候,还可能要先发布一个先行版本,具体可看 semver 规范。

可以使用 npm version 命令来修改版本号

npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]

栗子