手把手教你发布npm包 - 附完整示例

本文详细介绍了如何创建和发布npm包的全过程,包括npm基础知识、package.json配置、发布步骤、版本管理和最佳实践,帮助开发者将自己的JavaScript工具分享给全球开发者社区。

如何发布npm包 - 附示例详解

如果你使用过JavaScript,很可能接触过npm - 无论是安装Express、Lodash或React等包,还是运行npm init等命令。虽然使用npm对许多JavaScript开发者来说已是家常便饭,但有些人从未探索过这些包是如何创建、构建并与世界分享的。每个命令背后都是一个强大的系统,用于大规模构建、管理和分发JavaScript代码。

本文将指导你了解npm的基础知识,解释其幕后工作原理,并逐步演示如何创建自己的npm包并将其发布到官方npm注册表。无论你是刚接触JavaScript的初学者,还是使用过npm但从未发布过包的经验丰富的开发者,本指南都将帮助你自信地完成从设置到与全球开发者社区分享代码的整个过程。

目录

  • 什么是npm?
  • npm的组成部分
  • 命令行界面
  • 注册表
  • 网站
  • 什么是Package.json文件?
  • npm如何工作
  • 如何发布npm库
  • 如何验证和安装你的包
  • 如何更新你的包
  • 注意事项和最佳实践
  • 进阶内容
  • 结论

什么是npm?

npm,全称Node Package Manager,是一个用于安装和管理JavaScript包的命令行工具。它是一个为现代JavaScript开发(Node.js、前端工具、框架等)提供动力的生态系统。开发者使用npm来分享和借用包,许多组织使用npm来管理私有开发。

本质上,npm对于JavaScript就像pip对于Python或Maven对于Java一样。它使开发者能够重用他人编写的代码(大多数时候是为了实现项目中的功能),管理依赖关系,并与世界分享自己的代码。

你可以使用npm:

  • 在应用程序中获取和使用代码包,可以原样使用或进行自定义修改
  • 立即下载和运行独立工具
  • 使用npx直接从注册表运行包而无需安装
  • 通过npm注册表与全球开发者分享自己的代码
  • 限制对特定包的访问,以便只有经过批准的开发者才能使用它们
  • 创建组织来在一个地方管理代码、团队和包
  • 使用共享的组织帐户作为虚拟团队进行协作
  • 轻松处理包及其依赖项的不同版本
  • 通过与最新的包更新同步来保持应用程序最新
  • 探索提供相同问题不同解决方案的各种包
  • 与从事类似挑战和项目的开发者联系

npm的组成部分

npm由三个核心组件组成:

  • 命令行界面(CLI)
  • 注册表
  • 网站

命令行界面

你可以在终端上运行不同的npm命令。例如,npm init可用于初始化Node项目,npm install可用于安装包。它还允许你执行以下操作:

  • 发布包(npm publish)
  • 更新包(npm update)
  • 管理版本控制(npm version)
  • 运行脚本(npm run build、npm test等)

可以将其视为你的控制面板。

注册表

你可以在https://registry.npmjs.org找到巨大的公共数据库,包存储和共享在那里。它还包含围绕包的所有元信息。

例如,当你运行:

1
npm install express

npm会从注册表获取Express包。

npm注册表通过允许开发者以下操作来实现协作:

  • 发布自己的包
  • 安装他人创建的包
  • 发现新工具和库

其协作功能包括:

  • 开源包:代码公开可见(通常托管在GitHub上)
  • 版本控制:同一包的多个版本让用户可以安全地采用更新
  • 作用域包:命名空间允许团队和组织管理所有权
  • 问题和拉取请求:大多数npm包链接到GitHub,允许开发者贡献修复和增强功能
  • 组织:团队可以管理对共享私有或公共包的访问

网站

在https://www.npmjs.com,你可以:

  • 浏览包
  • 阅读文档
  • 查看下载统计信息和依赖关系
  • 创建和管理你的帐户、组织和包访问权限

什么是Package.json文件?

作为安装npm包的JavaScript开发者,你会遇到的一个非常重要的npm工具组件是package.json文件。它是一个元数据文件,位于每个npm或Node项目的根目录。它告诉npm(和其他工具)关于项目需要知道的一切,例如:

  • 项目叫什么
  • 它依赖什么
  • 如何运行它
  • 如何版本控制
  • 如何发布它

你可以将其视为JavaScript项目的蓝图。没有它,npm不知道如何处理你的代码。

你可以通过在终端中键入命令npm init并填写提供的提示来创建package.json文件。或者,你可以创建一个名为package.json的文件并手动用JSON内容填充它。

npm package.json文件中的关键字段

以下是常用字段列表以及它们如何与npm交互:

name和version

1
2
"name": "my-awesome-package",
"version": "1.0.0"

这是发布所必需的。

  • name必须是唯一的(如果发布到公共npm注册表)
  • version遵循语义版本控制(semver)(例如,major.minor.patch)

description、keywords、author和license

1
2
3
4
"description": "A utility to convert markdown to HTML",
"keywords": ["markdown", "html", "converter"],
"author": "Ikegah Oliver",
"license": "MIT"
  • 帮助npm用户发现你的包
  • 显示在npmjs.com上
  • 设置协作许可证

scripts

1
2
3
4
5
"scripts": {
  "start": "node index.js",
  "test": "jest",
  "build": "tsc"
}
  • 定义自定义命令
  • 使用npm run test、npm run build等运行
  • 自动化构建、测试、lint、部署过程

main和exports

1
2
3
4
"main": "dist/index.js",
"exports": {
  ".": "./dist/index.js"
}
  • main:require()或import的入口点
  • exports:控制包的哪些部分被暴露(特别适用于现代ESM和包安全性)

dependencies和devDependencies

1
2
3
4
5
6
7
"dependencies": {
  "express": "^4.18.2"
},
"devDependencies": {
  "eslint": "^8.0.0",
  "jest": "^29.0.0"
}
  • dependencies:项目在生产环境中运行所需的核心包(例如express)
  • devDependencies:仅在开发期间使用的包,如测试或构建工具(例如jest)

engines

1
2
3
"engines": {
  "node": ">=14.0.0"
}
  • 指定你的包支持的Node.js版本
  • 在用户使用不受支持的版本安装之前发出警告

private

1
"private":"true"
  • 防止意外发布到公共npm注册表
  • 用于monorepo和仅内部项目

files(可选)

  • 控制运行npm publish时包含哪些文件
  • 减少包大小,省略构建工件或测试文件

一个最小的npm package.json文件如下所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
  "name": "@oliver/markdown-to-html",
  "version": "1.0.0",
  "description": "Converts markdown to HTML with styles",
  "main": "dist/index.js",
  "scripts": {
    "build": "tsc",
    "test": "jest"
  },
  "keywords": ["markdown", "html", "converter"],
  "author": "Ikegah Oliver",
  "license": "MIT",
  "dependencies": {
    "marked": "^5.0.0"
  },
  "devDependencies": {
    "jest": "^29.0.0"
  },
  "engines": {
    "node": ">=14.0.0"
  },

}

package.json文件在每个npm工作流程中都扮演着核心角色。它定义了项目的身份,列出了其依赖项,指定了有用的脚本,并概述了包在发布时的行为方式。没有它,npm无法正确安装包、运行命令或将代码发布到注册表。

npm如何工作

当你在终端中键入npm install时,npm会启动一个幕后进程来为项目安装必要的包。根据你运行命令的方式,过程略有不同,如下所示:

方法1 - package.json已有依赖项

如果你的package.json在dependencies或devDependencies下列出了包,npm将:

  1. 读取这些条目:查看每个依赖项的名称和版本范围
  2. 联系注册表:npm查询https://registry.npmjs.org以获取每个所需包的元数据
  3. 下载正确的版本:选择符合你版本规则(如^4.17.0)的版本并下载.tgz文件
  4. 解包和安装:将包放入node_modules目录并缓存它们
  5. 更新package-lock.json:在此文件中记录确切的版本和依赖树,以确保以后安装的一致性

方法2 - 在没有现有依赖项的情况下运行npm install

如果你的package.json还没有任何依赖项,并且你在终端中运行如下命令:

1
npm install express

那么npm将运行:

  1. 解析包版本:获取Express的最新版本(除非你手动指定版本)

  2. 添加到package.json:npm自动将包添加到你的依赖项列表中,如下所示:

1
2
3
"dependencies": {
  "express": "^4.18.2"
}
  1. 创建package-lock.json(如果不存在):写入所有版本信息以便将来安装时锁定

注意:如果你运行npm install --save-dev jest,它会将包添加到devDependencies下。

如何发布npm库

要遵循本指南部分,你需要具备以下先决条件:

  • 稳定的网络连接
  • 带有终端的代码编辑器(如VSCode)
  • JavaScript和Node的基础知识

现在,让我们深入了解发布npm库。假设你刚刚构建并测试了一个很棒的JavaScript工具,你想与世界分享,并允许人们在他们的项目和应用程序中使用它,以下步骤将指导你从在本地机器上拥有该工具到将其作为npm包公开可用,供任何人安装和使用:

步骤1:创建免费的npm帐户

在发布之前,你需要一个npm帐户。

  1. 访问https://www.npmjs.com/signup
  2. 填写表格,包括用户名、电子邮件和密码
  3. 通过单击验证电子邮件中的链接确认你的电子邮件地址

步骤2:从命令行登录

创建帐户后,你需要通过终端登录。运行:

1
npm login

npm将提示你输入用户名、密码和电子邮件地址。如果一切正确,npm将在本地生成并存储身份验证令牌,因此你不必每次都登录。

步骤3:创建package.json文件

如果你的项目还没有package.json文件,通过在终端中键入以下命令来创建一个:

1
npm init

你将需要填写以下信息:

  • name:如果是公共的,必须是唯一的
  • version:从1.0.0开始(它代表项目的第一个版本;随后,你将在每次更新推送后相应更改它)
  • description:包的单行摘要
  • entry point:项目的入口文件,通常是index.js或dist/index.js
  • keywords:帮助他人发现你的包
  • author:你的姓名或GitHub句柄
  • license:使用MIT、ISC或其他开源许可证

完成后,npm将生成一个类似这样的package.json:

1
2
3
4
5
6
7
8
9
{
  "name": "my-awesome-package",
  "version": "1.0.0",
  "description": "A demo package for npm publishing",
  "main": "index.js",
  "keywords": ["demo", "npm", "tutorial"],
  "author": "Your Name",
  "license": "MIT"
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# my-awesome-package

一个简单的打招呼包。

## 使用方法

```js
const greet = require('my-awesome-package');
console.log(greet('Oliver'));
// 输出:Hello, Oliver!

步骤5:添加.npmignore文件

这将排除诸如node_modules、dist或.env之类的文件夹,以及你不想发布的包内的任何其他文件或文件夹。示例内容:

1
2
3
node_modules
.env
dist

步骤6:检查你选择的包名是否可用

在发布之前,检查你选择的包名是否已被占用。要检查,请在终端上运行此命令:

1
npm search my-awesome-package

或在浏览器中输入URL https://www.npmjs.com/package/my-awesome-package(将my-awesome-package替换为你选择的名称)。如果没有显示包页面,则该名称未被占用。

1
2
3
{
  "name": "@yourname/my-awesome-package"
}

步骤7:发布你的包

你现在准备好发布了。运行:

1
npm publish

如果你使用了作用域名称,在发布时必须将其设为公共:

1
npm publish --access public

如果一切有效,npm将发布你的包并给你一个URL,如: https://www.npmjs.com/package/my-awesome-package

如何验证和安装你的包

访问npm上的项目页面查看其在线状态。例如:https://www.npmjs.com/package/my-awesome-package,或在npm网站搜索栏中搜索你的项目名称。

现在,尝试在node项目中安装它:

1
npm install my-awesome-package

根据其构建的功能测试其特性和功能。

如何更新你的包

如果你在包中进行了更改或更新了功能,可以发布更新。

应用更改后,你可以在package.json中更新版本。使用语义版本控制,你可以按如下方式更新它:

  • 补丁更新:1.0.0 → 1.0.1
  • 次要更新:1.0.0 → 1.1.0
  • 主要更新:1.0.0 → 2.0.0

或者你可以使用CLI:

1
npm version <update_type>

<update_type>替换为你的新语义版本。

现在运行:

1
npm publish

注意事项和最佳实践

虽然发布到npm很简单,但你仍然需要遵循最佳实践来维护一个干净、安全且用户友好的包。

  • 排除敏感文件:切勿包含.env、凭据或密钥。使用.npmignore或package.json中的"files"字段来控制发布的内容
  • 发布前测试:运行npm pack以预览包,并在另一个项目中本地安装它以确保一切正常
  • 谨慎取消发布:你可以在72小时内使用npm unpublish --force取消发布,但避免频繁执行此操作,以防止破坏依赖你的包的其他项目
  • 始终提升版本:npm不允许你覆盖版本,因此在发布更新之前使用语义版本控制(npm version patch|minor|major)

进阶内容

既然你已经掌握了基础知识,你可以将npm技能付诸实践并提升为更高级的开发者。以下是一些你可以采取的简单、实用的步骤:

参与开源

维护自己的包

发布只是第一步。要真正掌握这个过程,请保持你的包最新。这包括修复错误、听取用户反馈和添加新功能。你将快速了解版本控制,确保你的包与旧项目保持兼容,并有效管理依赖关系。

深入研究高级功能

探索高级npm主题,如语义版本控制、使用私有包、创建作用域包以及使用CI/CD管道自动化发布。这些是任何专业开发者的基本技能。

采取这些步骤将帮助你从仅仅理解npm过渡到在真实场景中自信地使用它。

结论

恭喜!你现在已经学习了npm的基础知识,从package.json文件到使用npm库发布和维护JavaScript包。有了这些知识,你可以与世界分享你的JavaScript工具,与其他开发者协作,并为不断增长的开源库生态系统做出贡献。

通过遵循最佳实践、在本地测试并从标准错误中学习,你可以自信地创建对其他开发者来说干净、安全和有用的包。无论你是在构建小型实用程序还是完整的框架,在npm上发布都能让你的想法获得可见性,并帮助你为更广泛的JavaScript社区做出贡献。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计