我的第一個 npm 套件:把 vue component 打包到 npm 吧

一步步帶你從 npm 打包到 Demo page 的建置

Debby Ji
10 min readSep 7, 2019

前情提要

近期公司專案開始增多,但碰到一個問題,我們很多元件(component)都是共用的,那要怎麼將元件同步到各個專案呢?

最快的方法就是複製寫好的元件然後貼到各個專案,結案。(誤)

其實複製貼上看似很快,但是…

維護不易:一時貼上一時爽,一直貼上一直不爽(?),元件如果是一次性的就算了,但總會有更新的時候,當更新時就要再一次複製貼上到各個專案,不累嗎?

於是我們的解法是,把所有共用元件抽出去到另一個專案獨立管理,透過 npm 打包成套件,再引入到各個專案。剛好有機會能參與這個建置的過程,雖然做完了,但因為是公司的專案不便公開,於是用自己寫的 component 再做一次並用文章記錄下來。

這次要分享的是我自己寫的一個小小小元件,功能是可以選擇台灣的縣市地區的 select ,不會提太多元件本身,主要是講寫完元件後如何打包成 library 、如何發佈到 npm 以及透過 github 生成 demo page 等等。

專案建置

使用 Vue cli3 建立專案,此名稱只是專案的資料夾名稱,不會影響到後面的套件名稱,可自行取名

vue create vue-addresstw

檔案結構

dist/
docs/
src/
components/
address.vue
index.js
main.js
App.vue
package.json

稍微解釋一下

  • dist:打包成 npm 所輸出的 js 檔
  • docs:打包給 github 展示 demo page
  • components 裡的 index.js 檔很重要,這裡是打包成 npm 的入口檔案,而 App.vue 和 main.js 都是 demo page 的元件
  • package.json:打包成 npm package 最主要的依賴來源

元件建置

透過 yarn serve開發,就跟平常寫 component 時一樣,這邊就不詳細描述了,有興趣的可以去看我的專案

撰寫 install 安裝檔

vue 的 plugin 有分幾種,vue 文件其實就寫得蠻清楚,而我們要做的很簡單,僅僅是透過 Vue.component()添加一個(或多個)component。

// src/components/index.jsimport Address from './Address.vue'Address.install = function (Vue) {    Vue.component('vue-address', Address)}export default Address

在 components 的 index.js 檔撰寫一個 install 方法供 Vue.use() 使用, Vue.use() 是個全局呼叫的方法,當 Vue.use() 執行時,會呼叫 install 這個 function 並執行,以我的例子來說,就是添加 Address 這個 component。

若是多個 component 呢?

// 載入所有元件
import BaseButton from ‘./BaseButton/index.vue’
import BaseCheckbox from ‘./BaseCheckbox/index.vue’
import BaseInput from ‘./BaseInput/index.vue’

const Components = [
BaseButton, BaseCheckbox, BaseInput
]
const install = function (Vue, opts = {}) {
Components.forEach(component => {
Vue.component(component.name, component)
})
}
export default {
install
}

這邊是參考 ElementUI 所寫,總之就是透過 forEach 把每個 component 都註冊一遍。

build 指令

Vue-cli3 本身有提供 Library 的建置指令,超級方便!

vue-cli-service build --target lib —-name myLib [entry]

—-target lib表示這是打包成一個 library,name 會是打包後的檔名,entry 是打包入口,就放剛剛 install 的 index.js 檔

// package.json
{
"scripts": {
"build": "vue-cli-service build --target lib --name vue-address ./src/components/index.js"
},
...
}

將指令放入 package.json,透過 yarn build 指令打包,打包後會發現 dist 資料夾生了幾個檔

File                           Size                  Gzippeddist/vue-address.umd.min.js    76.04 KiB             14.43 KiB
dist/vue-address.umd.js 122.50 KiB 21.58 KiB
dist/vue-address.common.js 122.11 KiB 21.45 KiB

設定 package.json

接下來要好好的來寫 package.json 了,以往都是安裝套件跟寫 script 才用到,別忘了發佈到 npm 的設定當然也是在這裏

{
"name": "vue-addresstw",
"version": "1.0.0",
"main": "dist/vue-address.common.js",
"scripts": {
"build": "vue-cli-service build --target lib --name vue-address ./src/components/index.js"
}
}

先介紹一些必填的欄位

必填的有

  • name:npm package 的名稱
  • version:版本號,每次發佈都要大於過去的版本
  • main:主要的檔案入口,就是我們打包後的檔案

另外 private 不能設為 true(除非有升級 npm 帳戶),就直接刪除欄位就好

{
"name": "vue-addresstw",
"description": "A Vue component for select Taiwan county, city and zipcode.",
"version": "0.1.0",
"author": "Debbyji <jasmine820921@gmail.com>",
"main": "dist/vue-address.common.js",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build --target lib --name vue-address ./src/components/index.js",
"build:doc": "vue-cli-service build ./src/main.js --dest docs --mode development",
"lint": "vue-cli-service lint",
"test:unit": "vue-cli-service test:unit"
},
"repository": {
"type": "git",
"url": "git+https://github.com/jijigo/vue-addresstw.git"
},
"files": [
"dist/*",
"src/*",
"public/*"
],
"keywords": [
"Taiwan",
"address",
"zipcode",
"臺灣",
"郵遞區號",
"地址"
],
...
}

這邊是我完整的 package.json

其他常見的選填欄位,也可參考 creating a package json file

  • description
  • author
  • repository
  • keywords 各種關鍵字
  • homepage 首頁
  • files 選擇要上傳的檔案

npm 發佈

終於到了發佈這一步了

首先要先在 npm 申請帳號,Email 要經過驗證,就能透過指令登入

npm adduser // 新增使用者
npm login // 登入
npm whoami // 確認身份

然後⋯⋯一鍵發佈

npm publish
https://giphy.com

發佈之後,就能在自己的 npm 帳號裡看到囉!

使用套件

那要如何使用自己的套件呢?其實就跟很多的套件引入方式ㄧ樣

yarn add vue-addresstw// main.js
import vueAddresstw from 'vue-addresstw'
Vue.use(vueAddresstw)

因為是全局註冊,所以能直接使用 component

⋯⋯還沒結束!

建立 demo page

對於一個好用套件來說, demo page 是很重要的,它能讓你更快地展示你的套件將會長得如何、如何操作等等。

老實說,當我想使用別人套件時,都會第一個先看有沒有 demo page⋯⋯

沒有 demo page 的套件,就像工程師的履歷沒有附作品集一樣,讓人不敢用啊!

回到正題,我是透過 github 的 github pages 其中的 docs 方式(如果你想用別的方式也可以,就某些地方再調整)

首先,加一道指令:

// package.json
"scripts": {
"build:doc": "vue-cli-service build ./src/main.js --dest docs --mode development",
}

這裡的 build 就跟一般我們在打包網頁一樣,也就是原本的預設的 vue-cli-service build ,只不過因為我認為 npm 的 build 才是主體,就改了這裡的指令名稱變成 build:doc。

這裡要注意的是,輸出的資料夾預設是 dist,如果沒改的話會跟 npm 的 build 同個位置會把他的蓋掉,於是這裡加一個 —-dest docs,這樣就會打包到 docs 資料夾中。

再來,因為我們使用 github pages 的關係,打包的 publicPath 路徑要調整一下,預設是 /

// vue.config.js
module.exports = {
publicPath: './'
}

這樣就能打包了

yarn build:doc

打包完會看到 docs 資料夾多了 index.html、app.js、favicon.ico 三個檔案。

將檔案 push 到 github 後,在 settings 改 github pages 來源設定為 docs 如下圖,就完成了。

寫 README.md

我個人認為 README.md 也是寫套件時很重要的一部分,README.md 會出現在套件 github 的主頁,還有 npm 該套件的主頁,是別人來看你的套件時第一眼會看到的,比 demo page 更重要。

根據不同專案有不同用途,對於像我們的套件來說,通常就是簡單介紹套件,還有使用方法,甚至列出有哪些 props 跟 event 可以使用,就像一份文件一樣。

這邊其實用途很廣,也沒有硬性規定怎麼寫,我自己也還沒摸熟,大家有興趣可以多看看別人套件怎麼寫🌸

最後放上我的套件 github:vue-addresstw

心得

呼終於寫完了,真的很開心,終於寫出第一個 npm 套件!

特別感謝在公司剛好能有這樣的機會跟時間,自己動手摸索了一陣子也找了各種資源最後做出來了,成就感頗高!雖然可能還有多待優化的部分,但至少踏出了第一步。

這邊有個特別的心得,在做別人做過的東西時,除了 google 教學文章之外,看別人的 source code 對我更是莫大的幫助,像 ElementUI 就幫助了許多,還有一些 vue components ,找最接近自己需要的資源,我覺得看 source code 真的能學到很多!

感謝收看,希望有幫助到你,如果有問題請留言告訴我。

--

--

Debby Ji

Frontend Developer / 不趕快寫下來的話就忘記了