Skip to content

发布 NPM 包

1. 项目初始化

执行 npm init 创建 package.json 文件,需特别注意 name 字段的命名规则。普通包直接使用 package-name 格式,带范围的包必须采用 @scope/package-name 格式。此时系统会自动校验命名是否符合 npm 命名规范,包括长度限制(最大 214 字符)和禁用字符等。

2. 作用域包的特殊处理

当使用 @user/package 格式时,需在 package.json 中显式声明作用域:

json
{
  "name": "@your-username/package-name",
  "version": "1.0.0",
  "publishConfig": {
    "access": "public"
  }
}

作用域包默认视为私有(即使未订阅 npm 付费服务),必须通过 publishConfig.access 字段或命令行参数 npm publish --access=public 强制公开。

3. 模块入口设计

main 字段指定 CommonJS 入口文件(如 index.js),现代包建议同时配置 module 字段指向 ESM 模块文件(如 esm/index.mjs)。通过 exports 字段实现条件导出:

json
{
  "exports": {
    ".": {
      "import": "./esm/index.mjs",
      "require": "./index.js"
    }
  }
}

4. 发布前验证

运行 npm pack --dry-run 生成 .tgz 压缩包但不实际发布,可检查包含的文件结构是否符合预期。建议配置 .npmignore 文件排除测试用例、构建工具配置等非必要文件,该文件优先级高于 .gitignore

5. 认证与发布

执行 npm login 完成认证(需开启两步验证),随后使用精确发布命令:

bash
# 普通包
npm publish
# 作用域包首次发布
npm publish --access=public
# 后续更新
npm version patch && npm publish

6. 作用域包与普通包的区别

类似 @babel/core 的作用域包与普通包 babel-core 相比,具有以下优势:

命名空间隔离:作用域包通过 @scope/ 前缀创建虚拟命名空间,使不同开发者可以发布同名包而不冲突。例如 @babel/core@vue/cli 共享全局注册表但互不影响,这种结构特别适合组织级代码管理。

访问控制机制:普通包默认全局可见,而作用域包的可见性可配置。企业用户可通过 npm org 命令创建团队级作用域,配合 npm token 实现细粒度权限管理,这是普通包不具备的企业级功能。

7. 402 错误

发布公共范围的包时,可能会收到以下错误:

text
npm ERR! code E402
npm ERR! 402 Payment Required - PUT https://registry.npmjs.org/.... - You must sign up for private packages

尝试发布公共范围的包时会发生这种情况。默认访问级别为私有。要解决此问题,可以使用如下命令设置包的可访问性:

bash
npm config set access public

或者在 package.json 文件中添加以下配置:

json
{
  "publishConfig": {
    "access": "public"
  }
}