省流版: npx cnnc
為避免包名重複,取了2個單詞的首尾,cnpm sync
在開發一個多npm包的專案時,時常會一次更新多個包的程式碼,再批次釋出到 npm 映象源後。
由於國內網路環境的原因,大部分都會使用淘寶的映象源進行依賴安裝,為了確保釋出後,通過淘寶源能夠順利的安裝,通常會手動同步一下
cnpm sync vue react
但在一些大型的 monorepo 的多包工程裡,手動輸入包名是一件非常繁瑣的事情,所以準備把輸入的過程簡化一下,改成自動掃描工作區的包名,然後自動同步。
進而有了這個工具
直接通過 npx 執行即可,將自動掃描所有的包
npx cnnc
範例結果 如下
當然也同樣支援手動傳入要更新的包
npx cncc vue react
如果使用頻率較高,也可全域性安裝npm i -g cnnc
這樣可以直接通過cnnc
或cs
命令呼叫
核心程式碼不到20行,下面詳細的拆解一下,便於學習與理解
主要分為3部分
主要目的就是掃描工作區所有的 package.json
檔案,然後提取出包名(不包含 node_modules,build 等目錄下的檔案)
這裡可以 fs.readdirSync
實現一個遞迴的掃描,也可以用fast-glob,圖方便我這裡選擇後者,也是目前目錄掃描用得較廣泛的一個包
const fg = require('fast-glob')
const pkgNames = []
// 通過glob 取所有package.json
fg.sync('./**/package.json', {
ignore: [
'**/node_modules',
'**/dist',
'**/build',
'**/test',
// 省略更多的無關目錄...
],
absolute: true
}).forEach((file) => {
const { name } = require(file)
pkgNames.push(name)
})
通常工作區裡有很多無關的目錄,比如node_modules
、build
、dist
、test
等,這些目錄下的package.json
都不需要同步,所以可以通過ignore
引數來忽略掉,避免不必要的掃描(否則 node_modules 套 node_modules 會增加掃描時間,部分目錄是軟鏈的話也會導致掃描路徑的異常)
有些package.json
會包含 "private": true
內容,表明為私有的包,不會發布到npm映象源,所以需要過濾掉
// 省略其它程式碼
globResult.forEach((file) => {
const { name, private } = require(file)
if (!private) {
pkgNames.push(name)
}
})
最後一步就是呼叫cnpm sync
命令,這裡可以通過child_process
模組來實現
通過spawn
方法,可以直接呼叫命令列命令,然後通過stdio: 'inherit'
將命令列的輸出直接列印到終端中
const { spawn } = require('child_process')
const { promisify } = require('util')
function CnpmSync(...names) {
return promisify(spawn)('npx', ['cnpm', 'sync', ...names], {
cwd: __dirname,
stdio: 'inherit'
})
}
為防止使用者沒有全域性安裝cnpm,這裡通過npx cnpm sync
的方式來呼叫,這樣就不需要使用者自己安裝了
同時可以將cnpm
作為包dependencies
依賴安裝,通過cwd: __dirname
引數,將指令執行目錄指定為當前目錄,這樣npx cnpm
執行時,就會去cncc
目錄的node_modules
下找到cnpm
命令,從而實現呼叫,不需要重複的在全域性進行依賴的安裝,大大提升指令執行速度
工具原理很簡單,解決的問題也非常明確,希望能夠幫助讀者省下幾分鐘的時間,提升開發的幸福度
當然工具還有很多可優化的點,比如先通過對比 npm 和 cnpm 的版本號,如果一致就不需要同步了,這樣可以大大加快同步的速度
(目前由於網路原因從 npm 映象源拉包版本資訊相對較慢,所以本期沒有加這個功能,讀者如果有更好的建議,歡迎評論區交流)
同時可以將這個指令放在 "npm postpublish"
勾點中,這樣釋出後自動觸發同步,更加省心
完整原始碼見:GitHub