跳到主要內容
其他筆記

npm 發布流程

紀錄 Vue 2 元件的 npm 發布、dist-tag 與打包流程。

W

把寫好的年份選擇器(vue2-year-picker)發到 npm 的流程紀錄。前置作業只有一項:先去 npmjs.com 註冊帳號。

為什麼要另開一個發布專案

  • 元件是在既有專案裡寫出來的,但發布時要把它拆到一個乾淨的新專案,不要直接從原專案發。
  • 三個理由:
  • 專案獨立性:元件作為 npm 套件應該只有單一職責,專注在提供該元件的功能,不需要攜帶跟其他專案有關的程式碼。
  • 打包簡化:發布到 npm 時只需要包含與元件相關的檔案(編譯後的 .js 與 .css),不需要其他專案的內容。檔案體積小,使用者也不會被無關的東西搞混。
  • 方便維護:拆出來之後可以獨立更版、獨立寫文件、獨立發布,不會影響到原本的專案。

npm 的標籤(dist-tag)

  • 在講流程之前先搞懂標籤,因為它決定了「使用者裝到哪一版」。
  • 每個發布的版本都會被指到一個標籤,預設是 latest。
  • 使用者直接 npm install 拿到的就是 latest 指向的那一版。
  • 你可以自定義標籤,例如 next、beta、alpha,用來區分測試版與正式版。
  • 用測試標籤發布的版本,除非使用者明確指定,否則看不到也裝不到——這就是它的用處。

用測試標籤發布

npm publish --tag next

使用者要明確指定才裝得到:

npm install vue2-year-picker@next

不指定的話,拿到的是 latest(正式版):

npm install vue2-year-picker

測試標籤的用途

  • 內部測試:自己或團隊成員先裝來試
  • 提前試用:讓特定開發者先用到新功能並回饋
  • 不影響正式使用者:測試版不會被當成正式版,不會干擾別人的安裝

管理標籤

查看套件目前有哪些標籤與版本:

npm dist-tag ls vue2-year-picker

把某個標籤指到某個版本(沒有就新增,有就更新):

npm dist-tag add vue2-year-picker@1.1.0-beta.1 next

移除標籤:

npm dist-tag rm vue2-year-picker next

測試滿意後轉成正式版,就是把 latest 指過去:

npm dist-tag add vue2-year-picker@1.1.0 latest

建立發布專案

1. 初始化

npm init

2. 安裝相依套件

這裡發布的是 Vue 2 元件,所以要裝 2.6.0:

npm install vue@2.6.0 vue-template-compiler@2.6.0 --save
npm install -D @vue/cli-service

vue-template-compiler 的版本必須跟 vue 完全一致,差一個修訂號都會在編譯時報錯。

3. 目錄結構

vue-year-picker/
├── src/
│   └── YearPicker.vue
├── index.js
├── package.json
├── package-lock.json
├── LICENSE
└── README.md

4. 建立入口點

index.js:

import YearPicker from './src/YearPicker.vue';

export default {
  install(Vue) {
    Vue.component('YearPicker', YearPicker);
  },
};

// 支援按需引入
export { YearPicker };
  • install(Vue) 是 Vue 2 外掛的約定介面,讓使用者可以 Vue.use(YearPicker) 一次註冊全域元件。
  • 下面那行具名匯出則是給只想在單一檔案裡 import 的人用,兩種都留著比較有彈性。

5. package.json

{
  "name": "vue2-year-picker",
  "version": "1.0.0",
  "main": "dist/index.js",
  "files": [
    "dist"
  ],
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "vue-cli-service build --target lib --name YearPicker ./src/YearPicker.vue"
  },
  "peerDependencies": {
    "vue": "^2.6.0"
  },
  "author": "traveltime1221",
  "license": "MIT",
  "description": "一個用於只有選擇年份的 Vue2 組件,支持西元轉民國年份轉換。",
  "dependencies": {
    "vue": "^2.6.0",
    "vue-template-compiler": "^2.6.0"
  },
  "devDependencies": {
    "@vue/cli-service": "^4.5.19"
  }
}

幾個欄位的意義:

  • main:使用者 import 這個套件時實際載入的檔案
  • files:只有列在這裡的東西會被打包上傳。不寫的話整個資料夾(含 src/、測試檔)都會被發出去
  • peerDependencies:宣告「我需要宿主專案提供 vue 2.6 以上」,而不是自己再帶一份。元件套件一定要這樣寫,不然使用者的專案裡會出現兩份 vue,狀態不共用,畫面就開始出現各種靈異現象
  • --target lib:Vue CLI 的 library 模式,會產出 UMD 與 CommonJS 兩種格式

發布

確認打包內容

在真的發出去之前,先看看會包進去哪些檔案:

npm pack

它會產生一個 .tgz,解開來看就知道使用者實際會拿到什麼。這一步不要跳過——files 寫錯的話會把整個開發目錄發到 npm 上,而且 npm 的版本不能覆寫,只能再發一版。

打包

npm run build

登入

npm login

發布測試版

npm publish --tag next

裝來試:

npm install vue2-year-picker@next

轉正式版

npm dist-tag add vue2-year-picker@1.1.0 latest

測試標籤用不到了就刪掉:

npm dist-tag rm vue2-year-picker next

或者確認套件名稱在 npm 上是唯一的之後,直接發正式版:

npm publish

MIT License

授權要在發布前就決定好,發出去之後再改會很麻煩。常見的選擇:

  • MIT:最寬鬆,允許任何用途包含商業使用
  • GPL:強制要求其他人開源修改後的程式碼
  • CC BY-NC:只允許非商業使用

這裡選 MIT。它是世界上最簡單、最常用的開源授權之一,特點是:

  • 簡單易懂:條款只有幾段文字
  • 非常寬鬆:任何人都能免費使用、修改,包括商業用途
  • 保護作者免責:程式碼「按原樣」(AS IS)提供,別人用出問題不用你負責

範本(LICENSE 檔案):

MIT License

Copyright (c) [年份] [您的名字或團隊名稱]

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

發布後注意事項

  • 版本管理:每次更新記得改 package.json 的 version。npm 不允許重複發同一個版號
  • README.md:寫清楚怎麼安裝、怎麼用、有哪些 props,這是使用者唯一會看的文件
  • 測試:確保元件在 Vue 2 環境下真的能跑

相容性要顧到哪裡

發給別人用的東西,跟自己專案裡的程式碼標準不一樣——你不知道對方的瀏覽器版本與建置環境。

  • 想涵蓋大部分使用者,有幾個方向:

打包設定

  • Babel:把 ES6+ 轉成較舊的 JavaScript。用 .browserslistrc 或 Babel 的 targets 指定要支援到哪些瀏覽器
  • Polyfill:Promise、fetch 這類新特性舊瀏覽器沒有,用 core-js 補上
  • ESM / CommonJS 都給:現代工具吃 ESM,較舊的 Node.js 與前端工具吃 CommonJS,兩種都輸出相容性最高

多版本建置

  • ESM(ES Module):現代瀏覽器與 Node.js 都支援,模組化效率較好,可以 tree-shaking
  • UMD(Universal Module Definition):最廣泛支援的格式,瀏覽器與 Node.js 都能跑,用 <script> 直接引入也行

vue-cli-service build --target lib 預設就會同時產出這幾種格式,這也是選它的原因。

其他遇到的問題:舊 Node 需要 Python 2

切到比較舊的 Node 版本時(Node 14 以下),有些原生模組需要 Python 2 才能編譯。手上如果只有 Python 3 就會在 npm install 階段爆掉。

Python 也有版本管理工具,用 pyenv 裝一份 2.7 放著:

pyenv versions
pyenv install 2.7.18
pyenv global 3.9.6

pyenv 的完整用法另外寫在 pyenv 與 Python 版本管理。

2026 年後記

  • 本文保留 Vue 2 與 Vue CLI 的舊發布流程。
  • npm 的驗證、套件輸出與發布設定會隨工具版本改變,若重新發布套件請先核對目前 npm 與框架文件,也不要把發布憑證放進專案。

參考資料

分享這篇