发布指南
本文档说明如何把 @lh-ui/vue3 发布到 npm 公共仓库,以及如何把它托管到私有服务器(tarball 直链与 registry 元数据两种方式)。
发布支持手动与 CI 自动双通道:本地执行 changeset 命令,由人确认版本号与变更说明后再发包(下文「发布流程」);推送到 main 且 .changeset/** 有变动时,GitHub Actions 会自动执行 version + publish(见「GitHub Actions 自动发布」)。
前置准备
1. npm 账号与 scope 所有权
注册 npm 账号,开启两步验证(2FA)。
确认你的账号拥有
@lh-ui这个 scope 的发布权限:scope 是先到先得的,首次发布@lh-ui/*包的账号即成为该 scope 的 owner。本地登录:
bashnpm whoami # 确认当前登录账号 npm login # 未登录时按提示完成登录 + 2FA
2. 确认 registry 指向公共仓库
仓库根 .npmrc 只配了 shamefully-hoist = true,没有写死 registry,默认走 https://registry.npmjs.org/。package.json 的 publishConfig 也锁定了公共仓库:
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
}不要在仓库根
.npmrc里写私有 registry 地址——那会把发包也导向私有源。临时切换 registry 请用项目外的用户级~/.npmrc或命令行参数。
3. 一次发包包含什么
files 白名单只发布构建产物:es/(ESM + 类型 + 组件样式)、lib/(CJS)、dist/(UMD + 全量样式)。源码、文档、测试、脚本都通过 .npmignore 排除。执行发布命令时 prepublishOnly 会自动先跑一遍 pnpm build,所以不用手动先构建。
发布流程
第 1 步:写 changeset
每个用户可见的改动都应该有一条 changeset。如果本次改动已经写过了,跳到第 2 步。
pnpm changeset按交互提示选择 @lh-ui/vue3、bump 类型(major / minor / patch)和变更说明。
注意:本仓库的 changeset 是累积的。 当前
.changeset/下堆积了数十条未消费的 changeset,执行第 2 步的changeset version时会一次性全部消费、合并成同一个版本。如果你想分批发布,需要先用 git 分支或手动挪走部分 changeset 文件来控制节奏。
第 2 步:升版本号、生成 CHANGELOG
pnpm changeset:version这条命令会:
- 按 changeset 的最高 bump 级别计算新版本号,写入
package.json - 汇总所有 changeset 生成
CHANGELOG.md - 删除已消费的
.changeset/*.md(config.json里commit: false,不会自动提交)
执行后务必人工检查:
git status # 确认 changeset 被消费、CHANGELOG 已生成
git diff package.json # 确认版本号符合预期第 3 步:发布
pnpm changeset:publish它内部执行 pnpm publish,流程是:
- 触发
prepublishOnly→pnpm build(ESM / CJS / UMD / 类型 / 样式全量构建) - 按
publishConfig打包并推送到 npm 公共仓库 - 生成并推送 git tag(格式
@lh-ui/vue3@<version>)
因为 publishConfig.access 是 public,scoped 包也会公开可见,不需要额外加 --access public。
第 4 步:推送(由你执行)
git push --follow-tags发布前自检
正式发包前,用 dry-run 看一眼实际打包内容:
npm pack --dry-run确认输出里:
- 只包含
es/、lib/、dist/三个目录 - 不含
src/、packages/、docs/、tests/、scripts/、ai/ - 体积合理(UMD 全量包约 600KB,全量样式约 700KB,属预期范围)
发布后验证
# 1. npm 上能看到新版本
npm view @lh-ui/vue3
npm view @lh-ui/vue3 versions
# 2. 新建沙盒项目实测三种模块格式
pnpm create vite verify-pkg --template vue-ts
cd verify-pkg && pnpm add @lh-ui/vue3在沙盒项目里逐一验证:
| 验证项 | 写法 |
|---|---|
| 完整引入(ESM) | import LhUiPlus from '@lh-ui/vue3' + import '@lh-ui/vue3/dist/index.css' |
| 按需引入组件 | import { LhButton } from '@lh-ui/vue3' |
| 按需引入样式(需 sass) | import '@lh-ui/vue3/style/button' |
| 按需引入样式(免 sass) | import '@lh-ui/vue3/style-css/button' |
| 主题工具 | import { getThemeVars } from '@lh-ui/vue3/theme' |
| CDN(数分钟后刷新) | https://unpkg.com/@lh-ui/vue3 |
私有服务器托管(静态 tarball)
npm 公共仓库是主发布渠道;如果你需要一份自托管的镜像(内网使用、npm 被墙、或想锁定特定版本),把 tarball 放到你自己的服务器上是最轻量的方案,不需要搭建私有 npm registry。
1. 打包 tarball
pnpm build
npm pack生成的文件名是 lh-ui-vue3-<version>.tgz——npm 会把 scope 里的 @lh-ui/ 转成 lh-ui-vue3-(斜杠变连字符)。也可以用 npm pack --dry-run 提前确认。
2. 上传到服务器
沿用现有 nginx 站点的目录约定(文档站部署在 /home/webuser/nginx/lh-ui/vue3/),在其下新建 packages/ 目录,按版本分目录存放:
/home/webuser/nginx/lh-ui/vue3/
├── index.html # 文档站
└── packages/
├── 1.0.0/
│ └── lh-ui-vue3-1.0.0.tgz
├── 1.1.0/
│ └── lh-ui-vue3-1.1.0.tgz
└── latest # 软链,指向当前推荐版本
└── lh-ui-vue3-1.1.0.tgz对应 URL:
https://www.lhgb.top/lhui/vue3/packages/1.0.0/lh-ui-vue3-1.0.0.tgzpackages/ 是静态文件目录,复用现有站点的 nginx 配置即可,不需要新增 location:
# 已有的文档站 location 已覆盖 /lhui/vue3/ 前缀,
# packages/ 作为其子目录自动可访问,只需确保
# .tgz 的 Content-Type 能被下载(nginx 默认 octet-stream 即可)
location /lhui/vue3/ {
alias /home/webuser/nginx/lh-ui/vue3/;
autoindex off;
}3. 从私有服务器安装
三种等价写法,任选其一:
# pnpm
pnpm add https://www.lhgb.top/lhui/vue3/packages/1.0.0/lh-ui-vue3-1.0.0.tgz
# npm
npm install https://www.lhgb.top/lhui/vue3/packages/1.0.0/lh-ui-vue3-1.0.0.tgz
# yarn
yarn add https://www.lhgb.top/lhui/vue3/packages/1.0.0/lh-ui-vue3-1.0.0.tgz或直接写进 package.json:
{
"dependencies": {
"@lh-ui/vue3": "https://www.lhgb.top/lhui/vue3/packages/1.0.0/lh-ui-vue3-1.0.0.tgz"
}
}4. 注意事项
- 绕过 registry 依赖解析:tarball 安装不查 registry,依赖直接来自 tarball 内的声明。本包零运行时
dependencies,只有peerDependencies.vue,所以消费侧项目里有 Vue 3 就能装上、能跑。 - 没有版本元数据:
npm update对 tarball 依赖无效,升级必须手动换 URL(或改latest软链后重装)。适合做版本锁定镜像,不适合频繁更新。 - https 是必须的:pnpm / npm / yarn 默认拒绝 http 的 tarball 地址。
pnpm-lock.yaml里会是完整 URL + integrity hash:团队协作时锁文件可正确复现安装,无需访问 npm。
私有服务器托管(registry 元数据)
上面的 tarball 直链能用,但 pnpm update 无效、lockfile 里是一串 URL。若你希望消费侧像用普通包一样 pnpm add @lhgb/vue3、走版本解析与 dist-tags,可以让 Nginx 静态目录额外伪造一份 npm registry 元数据,充当只读 registry。两种方式可以共存。
1. 打包
pnpm build
node scripts/pack-private.mjs脚本做的事:把同一份构建产物改名为 @lhgb/vue3(仅 name / publishConfig 不同),npm pack 产出 tarball,计算 integrity(sha512)与 shasum(sha1),拼装 registry 元数据 JSON,输出到 private-registry/:
private-registry/
├── @lhgb/vue3 # 元数据 JSON(无扩展名)
└── tarballs/@lhgb/vue3/
└── lhgb-vue3-1.0.0.tgz常用参数:
--dry-run:只打印将生成的文件清单与元数据,不落盘,用于发包前核对--incremental:读取已有元数据再合并新版本,避免覆盖历史版本
2. 部署到服务器
把 private-registry/ 的内容上传到服务器目录,并套用 scripts/nginx-private-registry.conf.example 的 location(与文档站 /lhui/vue3/ 同一套 Nginx,独立 location):
/home/webuser/nginx/registry/
├── @lhgb/vue3
└── tarballs/@lhgb/vue3/
└── lhgb-vue3-1.0.0.tgzNginx 配置的关键是 default_type application/json——元数据文件没有扩展名,不强制声明类型客户端会按纯文本解析失败。完整配置见 scripts/nginx-private-registry.conf.example(.tgz 必须单独放在顶层正则 location,不能嵌套进 ^~ /lhgb/,否则前缀匹配会跳过正则):
location ^~ /lhgb/ {
alias /home/webuser/nginx/registry/;
default_type application/json;
autoindex off;
expires 5m;
}
location ~ ^/lhgb/(.+\.tgz)$ {
alias /home/webuser/nginx/registry/$1;
default_type application/octet-stream;
expires 1y;
add_header Cache-Control "public, immutable" always;
}3. 从私有 registry 安装
项目级或用户级 .npmrc 加一行:
@lhgb:registry=https://www.lhgb.top/lhgb三种包管理器统一:
pnpm add @lhgb/vue3
# 或
npm install @lhgb/vue3
# 或
yarn add @lhgb/vue34. 与公共包的关系
@lhgb/vue3 与 @lh-ui/vue3 同源同版本,构建产物完全相同,仅 name 与 registry 不同,二者可互换:
- 内网 / npm 被墙 / 需要锁定发布源的场景用
@lhgb/vue3 - 对外开放、希望被 unpkg / jsdelivr CDN 命中的场景用
@lh-ui/vue3
5. 注意事项
- 元数据要增量更新:每次发包后用
--incremental合并新版本,直接覆盖会丢失历史版本元数据,旧版本将无法安装。 - tarball 不可移动:元数据里的
tarballURL 是绝对路径,文件位置与 URL 必须一一对应。 - 同样必须 https:pnpm / npm / yarn 默认拒绝 http 地址。
- 不要把
@lhgbregistry 写进仓库根.npmrc:根.npmrc只保留shamefully-hoist = true,私服地址写到用户级~/.npmrc,避免污染发包链路。
GitHub Actions 自动发布
除手动流程外,.github/workflows/release.yml 提供自动发布通道:
- 触发条件:推送到
main且.changeset/**或package.json有变动;或仓库 Actions 页面手动触发(workflow_dispatch)。 - 行为:跑
pnpm build+pnpm verify:dts后执行 changesets/action 的 version + publish;没有待发布的 changeset 时什么都不做,所以挂在 push 上是安全的。 - 所需 secret:在仓库 Settings → Secrets and variables → Actions 配置
NPM_TOKEN——在 npm 生成 Granular Access Token,勾选@lh-ui组织的 publish 权限。
手动与自动通道可以并存:本地 pnpm changeset:publish 适合需要人工确认每一次发包的场景;CI 适合沉淀好 changeset 后自动滚雪球式发布。
回滚
# 标记某版本已废弃(推荐,不影响已安装的用户)
npm deprecate @lh-ui/vue3@1.0.0 "该版本存在 xx 问题,请升级到 1.0.1"
# 彻底下架:仅发布 72 小时内可行,且无其他包依赖时
npm unpublish @lh-ui/vue3@1.0.0CDN(unpkg / jsdelivr)的缓存会在数小时到一天内失效,回滚后可在沙盒项目用带版本号的 URL 验证旧版本是否仍可装。