發佈指南
本文件說明如何把 @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 驗證舊版本是否仍可安裝。