我在1月發表過一篇:從0搭建自動版本管理的Vue組件庫,是一篇搭建組件庫的todo類型的文章,包括組件庫的搭建、配置、打包、發佈。隨着公司前端基建愈來愈完善,咱們會產出愈來愈多的像這樣的前端庫,並且類型愈來愈多:組件庫、js庫、css庫,每一個庫都須要去從零開始搞搭建配置打包發佈,這種重複勞動顯然是不合理的,畢竟懶纔是第一輩子產力,那麼有沒有解決這個問題的好法子呢?因而我想到了Node Cli
,安裝更新簡單、流程統一規範、後續功能可挖掘潛力大,取代了重複勞動,讓前端組的同窗有更多的時間focus on coding,大喊真香。javascript
在搞以前弄清楚目標能夠有效避免作到一半遇到:我是誰?我在哪?我在幹嗎?的問題,咱們先來看看咱們的cli須要解決哪些具體的問題,我例舉幾個我工做中遇到的問題:css
npm version
對項目進行版本控制,每一個項目都要搞一份,在複製第二份的時候我就忍不了了,得抽出來。總結一下,咱們這個Node Cli
須要解決:壓縮構建產物、自動化版本控制、拉取標準發佈配置、自動打tag、下載庫模版或者組件模版。前端
以上是我遇到的問題,同窗們最好仍是結合本身的業務場景,看看Node Cli
能不能幫你幹掉一些重複性工做。vue
Node Cli
的原理是使用npm i -g cli-name
安裝後把包裝到全局的node_modules中,在命令行中執行指令後系統會按照node的環境變量去執行對應腳本。java
在cli項目的package.json中加入:node
{
...
"bin": {
"mycli": "./bin/mycli.js"
}
...
}
複製代碼
這樣當其餘同窗全局安裝時,就能直接使用mycli指令執行mycli.js這個腳本了。webpack
咱們本地開發時可使用npm link
將項目連接到包文件夾,這樣就能方便調試,不用每次都重建。git
接下來看一下mycli.js,在文件頂部添加#!/usr/bin/env node
,目的是解決不一樣的用戶node路徑不一樣的問題,讓系統動態的去查找node來執行這個腳本。web
這裏咱們要依賴一些優秀的第三方包了,這裏我選擇Commander.js
,它是node.js命令行接口的完整解決方案vue-cli
#!/usr/bin/env node
const { program } = require('commander')
const { resolve } = require('path')
const res = (command) => resolve(__dirname, '../src/', command) // 讀取腳本路徑
const version = require('../package.json').version
program.version(version, '-v, --version') // 執行mycli -v 或 mycli --version的時候輸出當前版本號
program.command('init').description('init lib').action(() => { // init腳本的描述與執行
require(res('init'))
})
program.command('build').description('build lib').action(() => { // build腳本的描述與執行
require(res('build'))
})
program.command('release').description('release lib').action(() => { // release腳本的描述與執行
require(res('release'))
})
program.parse(process.argv) // 處理輸出參數
複製代碼
ok,到此爲止cli的基本框架就搭好了,接下來就是豐富它的功能。
在功能愈來愈多以後,咱們的cli自己也可能會遇到體量龐大代碼結構複雜的問題,這時候咱們能夠將單獨的功能獨立打成npm包,由cli引入這些包,插件化方案能夠參考雲音樂前端技術團隊的文章:Node CLI 工具的插件方案探索(向大佬學習)。
上文提到的須要解決的問題裏,我將使用如下三個腳原本解決,主要說一下每一個腳本實現的思路,同窗們仍是根據業務須要本身實現腳本,想象力空間仍是比較大的。
先推薦幾個第三方庫,能夠幫助咱們更好更快的實現功能:
功能 | 說明 |
---|---|
request | http模塊 |
inquirer | 強大的用戶命令行交互工具,vue-cli也用的它 |
shelljs | 在node腳本中執行shell命令 |
chalk | 脫離黑白cli,給輸出加點顏色 |
ora | 命令行的菊花圖,執行耗時操做時咱們不但願用戶覺得cli卡死了 |
compressing | 用來壓縮的 |
node-emoji | 給命令行加一些emoji增長一些趣味(???) |
解決問題:下載庫模板和下載組件模板
咱們能夠把預設好的庫的模板就放在咱們cli的倉庫裏,或者放在專門的模板倉庫裏,而後經過gitlab的API去獲取下載,在使用gitlab API以前須要去帳號設置裏搞來一份private_token,調用API的時候帶上這個參數給gitlab作身份驗證,而後利用API遞歸的讀取gitlab倉庫裏的文件,對應的寫入到當前目錄下,就完成了庫模板的下載,期間能夠用ora搞點菊花圖,用node-emoji多整幾個綠色的勾勾增長一下用戶體驗。
解決問題:壓縮構建產物、自動化版本控制
使用inquirer跟用戶交互,能夠向用戶提問:使用哪一種npm version升級策略?打包的項目類型?庫的名稱?多入口的庫選擇入口文件?打包輸出路徑?可選的執行腳本?
在cli中咱們是能夠經過require(resolve('pathTo/package.json'))
去讀取用戶的package.json的,能夠獲取用戶項目的名稱、版本等信息,這些信息能夠做爲inquirer提問的默認值,畢竟每次打包都要用戶輸入的話體驗太差了,一路回車火花帶閃電確定纔是最爽的。既然能夠獲取到用戶的package.json,那咱們就能夠作一些約定的配置,好比約定用戶的package.json裏config.cli這個對象就是專門給咱們cli讀取使用的參數對象,用戶能夠寫一些定製化的配置。
我在項目中實踐的方案是使用inquirer得到的項目信息去拼湊出vue或者webpack的打包命令(公司主要用vue),例如vue組件庫的構建,最終會執行
npx vue-cli-service build --target lib --name name --dest path
複製代碼
webpack構建會執行
webpack --output-path path
複製代碼
在基礎的構建命令之上能夠從約定的config.cli中讀取用戶的配置,例如用戶有不一樣環境打包的須要就能夠添加env參數
打包後根據用戶package.json的name、version等信息,把構建產物放進/lib/front/projectName/version/xxxx.umd.js
而後用compressing壓縮成zip包
解決問題: 拉取標準發佈配置、自動打tag
拉取標準發佈配置和init相似,都是去下載一份標準的配置,能夠根據用戶的package.json進行一些改動再寫入。
自動打tag:我爲release指令提供了一個可選參數tag,能夠經過process.argv讀取,讀取到tag參數後,使用gitlab API爲對應分支打一個tag,後續build和release均可以先檢查這個tag版本和用戶package.json的版本,提醒用戶不要忘記升級版本。
cli能夠作的事情還有不少,只要想象力足夠而且業務有須要,能節省重複勞動時間,均可以集成進cli做爲cli的功能使用。
本文向你們介紹了Node Cli的使用場景和基本的框架搭建,提供了幾個功能的實現思路。
主要是給出本身在公司前端基建推動過程當中遇到的問題和解決問題的方案,並非業界最佳方案,但願你們若是有更好的方案和我討論,上述的方案不必定每一個公司每一個業務都通用,想要借鑑的同窗仍是建議從公司業務出發搞一份適合本身公司的cli。
我是suhangdev,歡迎與我交流前端相關話題,若是文章對你有幫助,請點贊支持噢,謝謝!