说实话,npm 包发布这件事,表面上看就是一条 npm publish 命令,但我第一次完整走下来的时候,踩的坑比想象中多得多。比如登录时 registry 还是淘宝镜像,publish 一直提示 403;后来换回官方源,又因为包名被占、files 字段没配好,把一堆不该进包的文件全打进去了。这篇指南算是我把整个发布流程完整捋过之后的记录,适合已经能写 Node 工具、但还没把自己代码发布成 npm 包的开发者,也适合那些发布过一次但被各种边界问题卡住的人。
实际上,一个 npm 包从代码写完到别人能 npm install 它,中间隔着包结构设计、构建产物配置、本地调试、registry 登录、版本管理、废弃与撤回等一整套环节。你不需要一次性全掌握,但第一次发布前按顺序过一遍,后面再发就轻车熟路了。下面我按自己的实操经验,从发布前决策开始,一直讲到后续维护和常见报错,尽量把每个环节的为什么也说清楚。
1. 发布前想清楚的三件事
1.1 你要发布的到底是个什么东西
很多新手上来就 npm init -y 然后写代码,结果发布出来的包四不像。第一步应该先明确包的形态,因为它直接决定 package.json 怎么配、要不要构建、要不要写 bin 字段。
常见的 npm 包大致分四类:
- 工具库:比如 lodash、dayjs 这种,被其他项目引用,导出函数或类。这类包需要配置 main/module/types,通常还要构建产物。
- CLI 工具:比如 vue-cli、eslint 这类,安装后通过命令行执行。这类包必须有 bin 字段,而且入口文件第一行要有
#!/usr/bin/env node。 - 组件库:主要面向 React/Vue 生态,除了 JS 逻辑还有样式、类型文件。这类包对 exports 字段的要求更严格,还要考虑 sideEffects。
- 配置包:比如 eslint-config-xxx、prettier-config-xxx,本质上是导出 JSON 或 JS 配置,通常不需要构建。
我自己发布过的工具库里,纯函数库最简单,CLI 工具最容易漏 bin 配置,组件库最费事。你写代码前先问自己一句:别人装了这个包之后,是 import 它、执行它,还是直接读取它?答案不同,后面所有配置都不同。
1.2 包名、作用域和版本号怎么定
包名是发布时的第一道关卡,因为 npm 上的名字是全局唯一的。命名规范上,npm 要求小写字母,可以用连字符和下划线,但不能有空格,不能用大写。个人经验是尽量用 xxx-utils、@scope/xxx 这种格式,既符合直觉又不容易冲突。
作用域包(scoped package)是解决命名冲突和权限隔离的关键。@scope/name 这种包名天然属于某个账号或组织,其他人没法占用。对于公司内部工具,强烈建议使用 @公司名/工具名 的格式,后续发布到私有源也方便。对于个人开源,如果包名没被占用,用普通短横线命名也行。
确定包名之前,先查一下是否已被占用:
bash复制npm view your-package-name
如果返回一堆信息,说明名字被占了;如果报 404,说明这个名字可用。版本号方面,遵循语义化版本 SemVer:主版本破坏性变更、次版本加功能、补丁修 bug。0.x 阶段比较自由,但一旦上了 1.0.0,就要对自己的版本纪律负责。我第一次发布时直接定了 1.0.0,后来才发现 API 还很不稳定,结果频繁发 breaking change,对早期用户很不友好。现在我的建议是:还没稳定之前,0.x 随便发,稳定了再上 1.0.0。
1.3 发行端和安装端不是一回事:npm、cnpm、pnpm 怎么选
我看很多人在讨论 npm 和 cnpm 的区别、npm 和 pnpm 的区别,但在包发布这件事上,要分清发行端和安装端。
发布的时候,你是在和 npm registry 打交道。官方源是 registry.npmjs.org,国内常用镜像源是 registry.npmmirror.com 这类。发布动作本身用 npm 官方客户端就行,但 registry 一定要指向你真正想发布到的仓库。如果你用 cnpm 客户端,它默认可能就指向镜像源了,往镜像源 publish 是非常不推荐的操作,镜像源一般也不接受用户发布代码。
安装端则是另一回事。用户可以用 npm、cnpm、yarn、pnpm 任选一种来安装你的包。这里就有个现实问题:不同包管理器的依赖解析逻辑不同。pnpm 用符号链接,node_modules 结构是严格缩进式的,不会把传递依赖提升到顶层;npm 和 yarn 则会提升依赖。作为包作者,你不能假设用户一定用 npm,更不能假设某个传递依赖一定存在于用户项目的 node_modules 顶层。所以包里的 dependencies 和 peerDependencies 必须写全、写准,不能靠“用户环境里碰巧有某个包”。
另外,pnpm 安装出的依赖树和 npm 不同,但作为发布者,你本地检查产物时还是应该用 npm 装一遍、用 pnpm 装一遍,双保险。至少保证包本身不依赖 hoisting 行为。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 包工程结构设计与构建配置
2.1 目录结构怎么摆,构建产物放哪
一个典型 npm 工具包的结构,我推荐这样:
text复制my-pkg/
├── src/
│ └── index.ts
├── dist/
│ ├── index.js
│ ├── index.mjs
│ └── index.d.ts
├── test/
│ └── index.test.ts
├── package.json
├── tsconfig.json
├── tsup.config.ts
├── README.md
└── LICENSE
src 放源码,dist 放构建产物,test 放测试,package.json 是核心。有一个很关键的思路:发布到 npm 的应该是 dist 编译后的产物,而不是 src 源码。当然如果只是纯 JS 零依赖小工具,不构建直接发布 src 也行,但一旦用了 TypeScript 或 JSX,就必须要构建。
dist 目录里通常需要 CJS 和 ESM 两种格式,外加类型声明 d.ts。Node 生态现在双格式混用很普遍:老项目 require 你的包,新项目 import 你的包,如果只发一种格式,就有一半用户用不了。
2.2 package.json 核心字段逐个说
package.json 是整个 npm 包的说明书。发布前至少要把下面这些字段搞明白:
| 字段 | 作用 | 说明 |
|---|---|---|
| name | 包名 | 发布时要求全局唯一 |
| version | 版本号 | 每次发布必须递增 |
| description | 包描述 | 会在 npm 检索和列表里显示 |
| main | CJS 入口 | 老版本 Node 会读这个 |
| module | ESM 入口 | 打包工具优先用这个 |
| types | TypeScript 类型入口 | 没有的话 TS 用户会抱怨 |
| exports | 子路径与条件导出 | 现代 Node 和打包工具都认这个 |
| files | 发布文件白名单 | 控制哪些文件进包 |
| bin | 可执行命令 | CLI 工具必须有 |
| peerDependencies | 对等依赖 | 组件库场景很关键 |
| publishConfig | 发布相关配置 | 可以写死 registry、tag 等 |
main、module、types 是经典三件套,但真正现代的做法是加一个完善的 exports 字段。exports 一方面能限定用户可以 import 哪些子路径,另一方面能区分 require 和 import 时加载不同的文件。
举个例子:
json复制{
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
"./package.json": "./package.json"
}
}
files 字段更要重视。它是个白名单,npm 发布时只打包 files 里列出的部分。如果你不写 files,npm 会默认把很多文件塞进包里,包括源码、测试、编辑器配置,甚至 node_modules(极端情况下)。写清楚 files 的好处是包体积小、传输快、用户拿到的东西干净。
注意:files 和 .npmignore 二选一即可,推荐用 files。files 是白名单模式,理解成本低,不会出现“我明明 ignore 了怎么还在包里”的诡异问题。
2.3 构建工具选型:tsup、tsc、rollup 怎么选
小工具和小库,我的首选是 tsup。它是基于 esbuild 的零配置打包器,能同时产出 CJS、ESM 和 d.ts,一条命令搞定。相比 tsc 需要单独配声明文件输出,相比 rollup 需要一堆插件,tsup 对个人开发者太友好了。
最小配置长这样:
ts复制// tsup.config.ts
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
dts: true,
clean: true,
sourcemap: true,
});
然后 package.json 的 scripts 里加上:
json复制{
"scripts": {
"build": "tsup",
"prepublishOnly": "npm run build && npm test"
}
}
prepublishOnly 这个钩子非常实用,它会在 npm publish 前自动执行构建和测试,能拦住一大批“忘记构建就发布”的失误。我自己第一次发布时就没用这个钩子,结果把上次的旧产物发出去了,用户拿到的代码和源码对不上,排查了很久才发现问题。
如果你包很小、就是纯 ES 库,用 tsc 直接编译也完全可以。组件库这类复杂场景再上 rollup 或 vite 的 library 模式。原则是:能用简单工具解决的,别引入复杂工具链。
2.4 发布前用 npm pack 检查产物
npm publish 之前,一定要跑一遍 npm pack --dry-run,它会在终端列出这个包即将包含的所有文件。这一步能发现 90% 的发布事故,比如:
- 忘了把 dist 加进 files,结果只有源码进包
- 把 test、src、tsconfig 等一堆没必要的文件都打进去了
- 包里出现了 .env、密钥等敏感文件
跑一遍长这样:
bash复制npm pack --dry-run
它不会真的生成 tgz,只是把文件列表打印出来。确认没问题后可以再跑 npm pack,会生成一个 tgz 压缩包,自己在本地项目里 npm install ~/path/to/my-pkg-1.0.0.tgz 实际装一遍,跑几个用例试试。这一套验证做完,再发布才稳妥。
3. 本地调试:发布之前先自测
3.1 npm link 的用法与坑
本地开发时,你通常不会先发布再测试,而是在一个项目里直接引用本地包。最常用的方式就是 npm link。
在包目录下执行:
bash复制npm link
这会在全局 node_modules 里创建一个符号链接指向当前目录。然后到你的测试项目里执行:
bash复制npm link my-pkg
这样测试项目里的 my-pkg 就直接指向本地源码目录了,改代码即时生效,不用反复 npm install。
不过 npm link 在 Windows 上有个常见的坑:如果报 npm : 无法加载文件 ...\npm.ps1,因为在此系统上禁止运行脚本,这是 PowerShell 执行策略拦住了脚本,不是 npm 本身坏了。解决办法在 6.1 会说,这里先记住可以用命令提示符 cmd 来跑,或者临时用 powershell -ExecutionPolicy Bypass 绕过。
用完记得解除链接:
bash复制npm unlink my-pkg
否则后续测试项目会一直指向本地路径,别人 clone 项目跑不起来,你又发现不了。
3.2 用 file: 协议做更简单的地本调试
如果只是临时联调,不想动全局符号链接,直接用 file 协议就行。
在项目 package.json 里写:
json复制{
"dependencies": {
"my-pkg": "file:../my-pkg"
}
}
然后 npm install,node_modules 里会出现这个本地包。改包源码后需要重新 install 才能生效,没有 npm link 的即时性,但胜在简单、不留残留。我的使用习惯是:需要频繁改代码用 link,只是验证一次是否可用用 file: 协议。
3.3 发布前自测清单
第一次发布之前,我建议你按下面这个清单逐项过一遍,每一项都不要太快跳过:
- 测试用例通过:
npm test必须全绿。 - 构建产物可运行:
npm run build后在临时项目里 import 一下。 - 类型声明正确:写一个
.ts文件 import 你的包,确认类型推导正常。 - 双格式加载正常:分别用
require('my-pkg')和import 'my-pkg'试一遍。 - README 写清楚:安装命令、最小使用示例、API 说明、许可证。
- package.json 字段完整:main/module/types/exports/files 都配好。
- peerDependencies 写对:组件库的 React、Vue 版本范围是否合理。
尤其是 README,我第一次发布时根本没当回事,结果有人看到包之后不知道怎么用,连 star 都没人点。后来补上了清楚的使用示例,情况立刻好了很多。npm 包的价值一半在代码,一半在说明。
4. 正式发布:从账号到 registry
4.1 注册账号与 npm login 的完整姿势
发布 npm 包的第一步是注册 npmjs.com 账号。注册时记得验证邮箱,我第一次发布时就没验证邮箱,结果 publish 直接报 403,提示需要验证邮箱才能发布。
接着在终端登录:
bash复制npm login
这里有个最容易踩的坑:如果你之前设置过国内镜像源(比如 registry.npmmirror.com),npm login 会往镜像源登录,后续 publish 就会报错或行为异常。登录前先看当前 registry:
bash复制npm config get registry
如果输出的不是官方地址,先切换:
bash复制npm config set registry https://registry.npmjs.org/
如果你在公司内网,用的是私有 npm 源,那就不能用官网账号登录了,而是用内网平台分配的账号密码,这种情况下.npmrc 里可能还需要配置 //registry.xxx.com/:_authToken=... 或者用户密码信息。具体凭据怎么填,看内网平台的文档,不要照抄公网的教程。
4.2 发布前环境检查清单
登录完别急着 publish,先跑一遍环境检查:
bash复制node -v
npm -v
npm whoami
npm config get registry
npm view your-package-name
npm whoami 能确认当前登录的账号,npm view 能确认包名是否冲突。如果你的包已经在 npm 上有同名包,publish 会报 403;如果版本号已经存在,会报 409。
另外,建议在 package.json 里写上 repository、homepage、bugs 这三个字段。写清仓库地址的好处是 npm 页面会自动显示“Repository”和“Issues”入口,用户报 bug 时能找到地方。开源项目顺手配上 LICENSE,MIT 或 Apache 二选一,别让人因为许可证问题不敢用你的包。
4.3 npm publish 执行流程与常见报错
环境确认没问题后,执行:
bash复制npm publish
发布成功后,终端会显示类似 + my-pkg@1.0.0 的输出。这时你去 npmjs.com 搜索包名,能看到页面、README、版本列表。
npm publish 常见的报错和原因,我自己整理了一份:
| 报错关键字 | 原因 | 处理方式 |
|---|---|---|
| 403 Forbidden | 包名被占用、未登录、邮箱未验证 | 换包名;重新 login;完成邮箱验证 |
| 401 Unauthorized | 登录态失效 | 重新 npm login |
| 409 Conflict | 版本号已存在 | 用 npm version patch 递增版本 |
| 402 Payment Required | 尝试发布私有包但账号无权限 | 检查是否误用了 "private": true 或私有源 |
| EINTEGRITY 或网络错误 | 上传大文件失败、代理问题 | 检查网络、临时关闭代理、重试 |
| 包内包含敏感文件 | files 配置缺失 | 用 npm pack --dry-run 自查文件列表 |
还有一条很隐蔽的:如果 package.json 里写了 "private": true,npm publish 会被直接拒绝。这是 npm 保护机制,防止误发布内部项目。检查一下就行。
4.4 公司内网与私有源的发布场景
很多开发者的场景不是开源,而是公司内网开发,需要把包发到私有 npm 仓库,比如 Verdaccio、Nexus 或企业级制品库。这种情况有个核心区别:registry 地址不是官方源,且通常需要内网账号认证。
推荐的做法是在包目录下建一个 .npmrc,只对本包生效:
ini复制registry=http://registry.company.internal/
//registry.company.internal/:username=yourname
//registry.company.internal/:_authToken=xxxxxxxx
注意别把账号密码纯文本提交到 git 仓库,容易泄密。更好的做法是让 CI 或本机 npm config 提供认证信息,仓库里只保留 registry 指向。
如果你的项目同时依赖外网公开包和公司私有包,建议注册表按 scope 区分。在项目根目录 .npmrc 里写:
ini复制registry=https://registry.npmjs.org/
@myscope:registry=http://registry.company.internal/
这样公开依赖走官方源,@myscope/ 开头的私有包走内网源,互不干扰。发布时同理,npm publish 默认发到当前 registry,如果你只想发私有包,记得在当前目录或全局配置好 @myscope:registry,或者用 npm publish --registry=http://registry.company.internal/ 显式指定。
5. 版本迭代、废弃与撤回
5.1 语义化版本与 npm version 命令
发布不是一次性动作,后续大概率要频繁更新。版本管理上,不要手动改 package.json 里的 version 字段,应该用命令自动处理:
bash复制npm version patch # 1.0.0 -> 1.0.1
npm version minor # 1.0.1 -> 1.1.0
npm version major # 1.1.0 -> 2.0.0
npm version 会自动更新 package.json、生成 git tag 并提交,省去手工同步的麻烦。但要注意,npm version 默认要求当前 git 工作区是干净的,如果没提交代码它会拒绝执行。
发布新版本的标准流程:
bash复制git add . && git commit -m "feat: xxx"
npm version minor
npm publish
git push origin main --tags
这样版本号、git tag、npm 上的版本一一对应,后续排查问题能对上号。0.x 阶段也要讲版本纪律,0.1 加功能、0.2 修 bug 这种习惯可以等稳定后慢慢建立。
5.2 用 dist-tag 管理测试版本
发布测试版本是常用操作,比如 beta、next、alpha 标签。
bash复制npm publish --tag beta
这样用户想安装测试版时,用:
bash复制npm install my-pkg@beta
而不是靠 1.1.0-beta.1 这种版本号去猜。dist-tag 是 npm 包发布里非常实用的机制,但很多人没用起来。看当前的标签列表:
bash复制npm dist-tag ls my-pkg
给某个版本手动打标签:
bash复制npm dist-tag add my-pkg@1.1.0-beta.1 beta
给稳定版本打上 latest 标签,是发布稳定版时默认行为,通常不需要手动处理。但一旦你发布了 beta 标签,别忘记最终发布稳定版时它会被标记为 latest,因此用户 npm install my-pkg 才会拿到正式版,而不是一直停在 beta 上。
5.3 deprecate、unpublish 与所有权变更
某版本完全不能用了,可以在 npm 上标记废弃,而不是直接删包:
bash复制npm deprecate my-pkg@1.0.0 "这个版本存在严重问题,请升级到1.0.1"
deprecate 之后,用户安装该版本会看到警告,但不会被强制阻断,这对双方都友好。
npm unpublish 则是真正把包从 registry 上撤掉。npm 对 unpublish 有严格限制:48 小时或 72 小时内的包可以撤,老版本通常不能撤。就算能撤,也要想清楚后果——所有依赖了该版本的用户的构建都会炸。我的一条铁律是:不到万不得已,绝不 unpublish,最多 deprecate。
所有权变更也用命令搞定:
bash复制npm owner add someone my-pkg
npm owner rm someone my-pkg
npm owner ls my-pkg
如果你要退出某个包的所有权,把自己从 owner 列表里移除即可。
5.4 用 CI 实现自动发布
手动发布容易忘这忘那,我后来把发布流程接到了 GitHub Actions 里。核心思路是:推 tag 时触发构建、测试、发布。
yaml复制name: publish
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org/
- run: npm ci
- run: npm run build
- run: npm test
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_TOKEN 需要在 npmjs.com 上生成 Access Token,然后配置到仓库的 Secrets 里。CI 里用 npm ci 而不是 npm install,因为 npm ci 会严格按 package-lock.json 安装,更快更稳定。这里也回应了很多人问的“npm install 每次构建都要做吗”——在 CI 里每次都做,但要用 npm ci 而不是 npm install,避免 lockfile 被意外修改。
6. 常见问题与避坑速查表
6.1 npm 命令找不到与 PowerShell 脚本被禁止
关于“npm 不是内部或外部命令”,本质上是环境变量 PATH 没配好,或者 Node.js 安装后没有正确生效。解决办法是检查 Node 安装目录是否在 PATH 中。Windows 下安装 Node 后,默认会把 C:\Program Files\nodejs\ 加入系统 PATH,但如果你用了解压版 node,就要手动把 node.exe 所在目录加进 PATH。配完之后新开一个终端窗口再验证 npm -v。
另一个高频问题是:
text复制npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本
这是 PowerShell 的执行策略(ExecutionPolicy)拦截了 npm.ps1 脚本。最简单的解决方式是临时绕过:
powershell复制powershell -ExecutionPolicy Bypass
然后再执行 npm 命令。也可以永久放开当前用户的限制:
powershell复制Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
RemoteSigned 保证本地脚本可以运行,而远程下载的未签名脚本会被拦截,比 Unrestricted 安全很多。如果你完全不想碰 PowerShell,切到 cmd 或 Git Bash 里跑 npm 也行,那些环境不存在这个策略限制。
6.2 安装与构建时的警告到底要不要管
现在 npm 安装依赖时经常看到大量 deprecated 警告,比如:
text复制npm warn deprecated node-domexception@1.0.0: use your platform's native DOMException
这通常是某个老依赖包的作者在提示它已过时。大部分情况下你不需要立刻处理,只要功能正常,升级依赖时可以顺手清掉。真正要留意的是安装失败类错误。
EPERM 错误在 Windows 上很常见,通常是文件被占用或权限不足。我之前遇到一次是编辑器开着 node_modules 里的某个文件,结果 npm install 一直 EPERM。解决方式是关掉编辑器、删除 node_modules,再以管理员权限重装:
bash复制rm -rf node_modules package-lock.json
npm install
还有 npm 9 以后对依赖安装脚本(postinstall)默认禁用的警告,比如:
text复制npm warn install-scripts run npm install -g --allow-scripts=@anthropic-ai/claude-code
这是 npm 出于安全考虑,限制了依赖包在安装时执行 node-gyp 等编译脚本。如果某个包确实需要构建脚本,需要显式加上 --allow-scripts 参数。
还有一个极端情况:有人在项目里执行了 npm install --force,然后看到:
text复制npm warn using --force recommended protections disabled
--force 会绕过大量依赖冲突检查,虽然能装成功,但可能装出不兼容的依赖树。能不用就不用,真要绕过 peerDependencies 冲突,用 --legacy-peer-deps 会温和很多,也就是热词里有人打的 npm i -legacy-peer-deps(正确写法是 npm i --legacy-peer-deps)。
6.3 镜像源切换与发布 registry 混用
国内开发环境几乎都会配镜像源,最常见的是淘宝镜像。但要注意,镜像源是给安装依赖用的,不是给发布用的。如果你把全局 registry 设成了 https://registry.npmmirror.com/,然后直接 npm publish,很多情况下会发布失败,因为镜像源不一定支持/允许上传新包。
我自己的做法是,全局 registry 保持官方源,只在需要加速安装时用命令行参数或项目级 .npmrc 临时切换:
bash复制npm install --registry=https://registry.npmmirror.com/
或者用 nrm 快速切换:
bash复制npx nrm use taobao
# 发布前切回
npx nrm use npm
还有一个更稳妥的方法:在 package.json 里写死发布地址,防止误发到镜像源:
json复制{
"publishConfig": {
"registry": "https://registry.npmjs.org/"
}
}
这样不管本机全局 registry 配成什么,npm publish 都会发布到官方源。企业私有源同理,把 publishConfig 指向内网仓库即可。
如果你在公司内网,需要走代理才能访问 npm registry,可以配置:
bash复制npm config set proxy http://user:password@proxy.example.com:8080/
npm config set https-proxy http://user:password@proxy.example.com:8080/
内网代理需要用户密码时,这个配置就派上用场了。注意不要把代理配置提交到 git 仓库,特别是含密码的。
6.4 其他高频问题速查
依赖名开头带 _、npm run dev 报错这种,我遇到过几次。这通常是因为 node_modules 目录被某种压缩工具或同步工具处理过,目录名或包名被改写了,导致依赖解析失败。解决方案只有一条:删掉 node_modules 和 lockfile,重新执行 npm install 或 npm ci。不要试图手动改目录名,改不完的。
npm run make 出现 unhandled rejection 之类的问题,多半是某个生命周期钩子或打包脚本异常,常见于 Electron forge 项目。这类问题先看完整堆栈,找到具体报错模块,别被表面的 unhandled rejection 吓到。
还有包体积相关的优化。发布时检查一下 tgz 大小,如果超过几百 KB 且里面有很多冗余,检查 files 配置、检查是否不小心把源码 map 打进去了。现在很多项目用 sourcemap 调试,但如果是发布工具库,我建议默认不发布 sourcemap 或者只发布 JS 源码简单格式的。体积大了会直接影响用户的下载安装速度,尤其是国内网络环境下,大包更容易把镜像源拉胯。
我自己做包发布做得多了之后,最大的体会是:真正决定一个包好不好维护的,不是 publish 那一下,而是发布前的结构设计和发布后的版本纪律。如果你只想图省事,直接 npm publish 也能发出去,但后面每改一次版本、每修一个 peerDependency 问题,都会回来找你要账。建议新手第一次发布时把 npm pack --dry-run 和 npm link 这两个动作强制自己做一遍,能省掉后面大量问题。就先聊到这里,祝你第一个包顺利上线。
