?vue元件釋出npm最佳實踐

levy9527發表於2018-06-15

我們經常使用元件,二次封裝或創造元件,在團隊內部使用; 可當我們想通過npm分享元件時,卻沒了之前的得心應手,本文旨在幫助大家在可以更輕鬆地釋出元件

首先,把vue元件釋出到npm這件事可以拆分成兩個部分:

  1. 在npm上釋出一個包

  2. 將vue元件打包

npm發包

有人說,發包不是一行命令就搞定了麼

npm publish複製程式碼

是的,可是還忽略了以下幾點:

  1. 首先你要在npmjs上註冊一個賬號

  2. 檢視你的.npmrc設定,確保你的registry是www.npmjs.com/, 而不是淘寶源

  3. 在終端npm login,登入你的賬號

做好以上三點,才可以通過npm publish簡單地釋出一個包。若要遵循最佳實踐,還有一些準備工作要做好,下面將為你講述

完善基本資訊

package.json的以下欄位需要注意

  • name

  • version

  • description

  • keywords

  • author

  • license

  • repository

  • main

  • unpkg

  • module

  • scripts

  • engines

name就是釋出到npm上的包名,也即別人安裝時輸入的名字yarn add ${name}, 包名應該是kebab-case, 即英文單詞全小寫,中劃線分割(lower case and dash-separated)

version是語義化的,major.minor.patch. 如果是major變動,通常意味著不相容的修改; 如果是minor,意味著新增向後相容的新功能,如果是patch, 意味著bug的修復。詳情見semver.org

description是對包的描述,在npmjs.com上搜尋時會顯示,有助於使用者在搜尋時進行篩選

keywords 同樣也是幫助使用者查詢到你的包

author的格式一般是${your name} ${email}, 當然也可以是一個github地址

license可能很多人會忽略,最好也寫上去。至於用哪個,vue的官方專案全是MIT,因此我也是MIT,不糾結

repository的格式參考如下:

"repository": {
  "type": "git",
  "url": "https://github.com/FEMessage/el-data-table.git"
}複製程式碼

這樣在npm包頁面就有會個github的入口

main定義了包的入口檔案,在NodeJs環境,語句import pkg from 'package-name'時,其實匯入的就是main定義的檔案,它可以是CommonJs格式的, 也可以是umd格式

需要注意的是,當你把一個包釋出到npm上時,它同時也可以在unpkg上獲取到。也就是說,你的程式碼既可能在NodeJs環境也可能瀏覽器環境執行。為此你需要用umd格式打包,並且在package.json定義unpkg欄位,一般而言此時它的命名為name.min.js

最後,別忘了定義modulejsnext:main欄位,它表示用ES6模組格式打包,給Webpack 2+或Rollup等先進的構建工具來處理。

我們來看一下三個欄位的示例:

"main": "dist/el-data-table.js",
"unpkg": "dist/el-data-table.min.js",
"module": "dist/el-data-table.esm.js"複製程式碼

scripts 為了防止出現發包前忘記構建的烏龍事件,定義一下發布前的指令碼, 這樣每次執行npm publish前都會先執行npm run build

"prepublishOnly": "npm run build"複製程式碼

engines 可以告訴使用者執行你的包對NodeJs版本的要求,這是非常重要的,不然你使用了NodeJs新版本特性,卻沒有定義該欄位,導致低版本NodeJs使用者執行報錯,讓人摸不著頭腦。

定義依賴

當你開發一個專案時,比如一個靜態網站或一個單面應用,dependenciesdevDependencies並沒有太多區別,因為你npm installyarn時,這些依賴都會下載下來,因為你是在開發。

但對於釋出到npm的包則不同:

dependencies 是執行你的包必須安裝的依賴,即當使用者yarn add my-awesome-package時,這些依賴也會下載。

devDependencies 是開發你的包時需要安裝的依賴,比如eslint, jest等開發工具,當使用者yarn add my-awesome-package 時,這些依賴並不會下載!

peerDependencies 一般用於開發外掛的場景,它要求使用者必須預先安裝了某些依賴。比如開發webpack的外掛,如果你把對webpack的依賴定義成dependencies, 如果使用者安裝的webpackdependencies裡的minor版本不一致, 則使用者yarn add my-webpack-plugin時會把dependencies定義的webpack也下載下來,也即使用者會安裝兩個major版本相同的webpack, 這就不合適了。

所以說,定義好你的包的依賴,可以讓使用者安裝使用你的包時少點困惑,多些愉悅。

忽略檔案

如果有 .gitignore檔案,則釋出時會忽略 .gitignore中定義的檔案; 也即這些檔案不需要在.npmignore重新定義。如果用.gitignore忽略了dist目錄,但發包時又需要釋出dist目錄,此時可以在package.json定義files欄位,這是一個白名單,裡面的檔案都會被髮布出去

"files": [
  "dist"
]複製程式碼

需要注意的是,子資料夾.gitignore.npmignore同樣有效,而它們會覆蓋files欄位

另外,有些檔案無論如何設定,都不會發布出去:

  • node_modules

  • .git(包括.gitignore)

README.md

別忘了這個檔案,寫下與包相關的更具體的資訊,告訴使用者這個包有哪些功能,如何使用。這很重要,使用者不會使用一個沒有文件說明的包!

釋出

一個版本只能釋出一次,為了避免每次手動修改package.json, 可以使用npm version [major | minor | patch]命令來更新package.json裡的版本

打標籤

假設你的包最新版本是1.0.0, 當使用者yarn add my-awesome-packageyarn add my-awesome-package@1.0.0時,其實是相當於yarn add my-awesome-package@latest, 即不指定標籤安裝時,預設安裝latest版本。

假設你正在開發2.0.0版本,它還不穩定,你想釋出它讓使用者測試一波,此時又不能讓它變成latest版本,不然使用者yarn add my-awesome-package時就安裝了2.0.0了,那將讓使用者崩潰。這時該怎麼辦呢?標籤就用上場了。

可以這樣釋出

npm publish --tag beta複製程式碼

則使用者yarn add my-awesome-package安裝的是1.0.0版本, yarn add my-awesome-package@beta時,安裝的是2.0.0版本,不影響老使用者,棒!?

記住,你只能對一個版本打一個標籤,使用npm dist-tag ls 可以檢視npm包一共打了幾個標籤

打包Vue

腳手架

經過一番折騰,在Vue Conf上找到一個vue元件的打包腳手架(vue官方文件也有說明),進行“本土化”修改完善後,已在github開源:github.com/FEMessage/v…

說明

我們以開源元件el-data-table為例,解釋目錄結構及檔案

├── README.md
├── build
│   └── rollup.config.js
├── dist
│   ├── el-data-table.esm.js
│   ├── el-data-table.min.js
│   └── el-data-table.umd.js
├── docs
│   ├── build
│   └── index.html
├── package.json
├── src
│   ├── el-data-table.vue
│   └── index.js
├── styleguide.config.js
├── test
│   └── index.test.js
└── yarn.lock複製程式碼

先來看三個檔案:

  • README.md

  • package.json

  • yarn.lock

README.mdpackage.json大家都懂,有yarn.lock因為是我們鼓勵大家使用yarn, 它比npm更快。雖然npm 6.0號稱提速17倍(可以想象6之前是得有多慢?),但經測試,還是不如yarn

接下來看build, dist, src 目錄

├── build
│   └── rollup.config.js
├── dist
│   ├── el-data-table.esm.js
│   ├── el-data-table.min.js
│   └── el-data-table.umd.js
├── src
│   ├── el-data-table.vue
│   └── index.js複製程式碼

build 目錄下放編譯時的配置檔案,這個跟vue-cli 2.x生成的模板build目錄作用是一樣的,只不過這裡放置的是rollup.config.js。至於為什麼用Rollup, 一是因為配置更簡單,二是因為它更適合打包類庫,當原始檔中有import lib from 'awesome-lib'類似的程式碼時,Rollup並不會把awesome-lib捆綁輸出,這正是開發類庫或元件需要的特性

dist是輸出目錄,也有叫lib的,我也糾結了好久。看了一些優秀的開源專案,發現叫dist的比較多,而webpack4預設的輸出目錄也是dist, 因此決定用dist。至於dist目錄下會有三個檔案,前文已說過原因。而命名為何不是camelcase, 而是kebab-case, 後面風格指南會說到

src是輸入目錄。把index.js放在src目錄,也是經過一番考慮。也想把index.jspackage.json同級,最終參考了webpack4, 它預設輸入是src/index.js, 那就跟主流保持一致。該檔案主要工作是把src目錄下的vue檔案設定成vue的外掛。同樣,vue檔案的命名後面風格指南會說到

├── test
│   └── index.test.js複製程式碼

test目錄下是基於jestvue/test-utils的單元測試檔案,具體教程可參考官方文件

├── docs
│   ├── build
│   └── index.html
├── styleguide.config.js複製程式碼

docs存放的是元件的api文件,包含props, slot, event等內容的說明,使用的是vue-styleguidist作為vue元件文件生成工具。為啥叫 docs呢,因為Github Pages支援從master分支的docs目錄讀取檔案,在倉庫Settings裡選擇Github PagesSource即可, 具體看官方文件

風格指南

vue元件把template/script/style都放在一個vue檔案裡,這個稱之為單檔案元件,Single File Component,縮寫為SFC, 這就是vue-sfc-cli中sfc的寓意

通讀vue官方風格指南, 由於我們是kebab-case的重度使用者,因此我們更看重的是在多個專案中保持相同的大小寫規則,以下是摘取的適用於我們團隊協作習慣的指南:

這樣做可以避免跟現有的以及未來的 HTML 元素相沖突,因為所有的 HTML 元素名稱都是單個單詞的

我們選擇使用kebab-case

好例子:

components/
|- my-component.vue複製程式碼

好例子:

<!-- template -->
<my-component></my-component>複製程式碼

這裡我們選擇使用PascalCase, 因為在程式語言裡,kebab-case並不是最佳實踐。 也即,在非程式語言的範圍,我們能用kebab-case就用

好例子:

Vue.component('MyComponent', {
  // ...
})
​
import MyComponent from './my-component.vue'export default {
  name: 'MyComponent',
  // ...
}複製程式碼

綜上所述,就可以明白前文中el-data-table的檔案命名風格為kebab-case的原因了

更多文章請檢視我的部落格

參考

  1. How to publish your package on npm

  2. module-best-practices

  3. npm-style-guide

  4. semver.org

  5. unpkg

  6. umd

  7. npm scripts

  8. .npmignore

  9. 2018 Vue Conf

  10. Vue Cookbook

  11. Vue Style Guide

  12. npm-vs-yarn

  13. Github Pages


相關文章