組件庫本地調(diào)試自動化方案

背景

日常開發(fā)中,一個項目的代碼往往不只在一個項目倉庫下,一些功能獨(dú)立、復(fù)用性強(qiáng)的組件或者工具函數(shù)等,可抽離成單獨(dú)的通用組件,通過依賴包的形式安裝進(jìn)來,其他同學(xué)也可以很方便地在其他項目中調(diào)用。比如業(yè)務(wù)項目叫my-project,抽離的組件庫@cute/hello發(fā)布到npm上,項目中通過npm install @cute/hello --save,就可以直接引用組件庫了。

調(diào)用組件庫是一件很快樂的事情,只需要調(diào)調(diào)API就能實(shí)現(xiàn)。但是如果組件庫有bug,你想在組件庫下調(diào)試完畢后,在真實(shí)有問題的項目環(huán)境去開發(fā)調(diào)試,卻無從下手。有人想到可以先npm publish發(fā)布一個測試的beta包,再在項目中npm install,但這樣一來一回頻繁調(diào)試的時候就浪費(fèi)了很多時間,況且第三方組件庫不允許你去操作發(fā)布測試的。怎么能做到組件庫開發(fā)和調(diào)試時像內(nèi)嵌在項目的代碼一樣流暢,無額外感知成本呢?那么這就涉及到組件庫的本地調(diào)試了。

image.png

下面會先介紹三種常見組件庫本地調(diào)試方法,最后會總結(jié)一種自動化調(diào)試方案:使用nodemon+yalc實(shí)現(xiàn)自動化調(diào)試本地組件庫。想直接看自動化調(diào)試的可以跳到最后面。

1、 常用的npm link方式

2、 修改項目package.json依賴路徑

3、 復(fù)制構(gòu)建的組件庫產(chǎn)物到項目庫的node_modules下

4、 自動化調(diào)試方案:nodemon+yalc

說明:文中所講的組件庫、library、依賴包、開源庫等詞匯在此均指同一概念,即抽象出來的通用組件。

以往的調(diào)試方式

大致來看,會有幾種常見的調(diào)試方式,但是都有其局限性。

1. 常用的npm link方式

通過npm link的方式建立組件庫和項目之間的聯(lián)系,這也是較常用的方式。每當(dāng)組件庫代碼變更后,通過在組件庫發(fā)布代碼所在目錄執(zhí)行以下

npm run build // 執(zhí)行構(gòu)建
cd dist // 進(jìn)入構(gòu)建后結(jié)果目錄
npm link // 將 library 鏈接到全局

然后到項目所在目錄重新綁定并重啟服務(wù)。

npm link @cute/hello
npm run start // 對應(yīng)到具體執(zhí)行腳本
image.png

npm link后輸出和項目綁定link示例如下,通過執(zhí)行發(fā)現(xiàn),組件庫npm link后會在發(fā)布代碼目錄下也生成一個node_modules會用來存放組件庫自身依賴的dependencies。my-project執(zhí)行npm link @cute/hello后會把組件庫發(fā)布目錄下的代碼都同步到項目的node_modules下了。

?  cute-hello git:(xxx) cd dist
?  dist git:(xxx) npm link
npm notice created a lockfile as package-lock.json. You should commit this file.

added 4 packages from 6 contributors and audited 4 packages in 4.75s
found 0 vulnerabilities

/usr/local/lib/node_modules/@cute/hello -> /Users/user/cute-hello/dist

?  my-project git:(xxx) npm link @cute/hello
/Users/user/my-project/node_modules/@cute/hello -> /usr/local/lib/node_modules/@cute/hello -> /Users/user/cute-hello/dist

my-project 與本地組件庫 npm link 后,它的 node_modules 中的 @cute/hello 代碼是本地組件庫發(fā)布目錄 link 后的代碼。

每次組件庫代碼更改后,在組件庫進(jìn)行 npm run build 操作后,項目執(zhí)行 npm link 后,它會去 link 的地址去找資源文件(也就是組件庫),所以它的資源文件不在項目下,webpack不會對其做預(yù)編譯,所以如果組件庫本身還依賴其他的依賴庫,需要每次構(gòu)建后在組件庫執(zhí)行npm link,它才會自動生成組件庫自身依賴并注入 node_modules 中 ,這樣項目庫才能找到組件庫的依賴,不然會導(dǎo)致實(shí)際構(gòu)建或者運(yùn)行時報錯,項目庫會找不到組件庫自身的依賴。

image.png

調(diào)試完畢后解除link操作,項目重新 npm install 依賴

npm uninstall -g @cute/hello // 解除組件全局link

整個調(diào)試流程如下圖。

image.png

操作成本:

  • 每次組件庫修改需要build構(gòu)建
  • 組件庫有自身依賴時構(gòu)建后需執(zhí)行npm link和項目重啟服務(wù)
  • 結(jié)束調(diào)試后解除link,安裝正確的生產(chǎn)依賴包
  • 組件庫和項目庫都有調(diào)試成本

適用場景:

  • 在一些命令行工具庫里面尤其好用,完全零調(diào)試成本,全局的命令行工具甚至不需要在項目庫安裝依賴包就能調(diào)試;
  • 組件庫自身沒有依賴的簡單情況下

2. 修改項目package.json依賴路徑

修改 package.json 中組件庫為本地組件庫路徑,需要在項目庫重新執(zhí)行 npm install 安裝依賴。但是項目庫中安裝依賴,實(shí)際上是把依賴安裝到組件庫下了,項目下并沒有把組件庫自身依賴安裝到項目下。

// package.json
"dependencies": {
    "@cute/hello": "file:/Users/user/cute-hello/dist",
}

可以看到 package-lock.json 中組件自動引用本地相對路徑

// package-lock.json
"@cute/hello": {
      "version": "file:../cute-hello/dist",
      "requires": {
        ...
      },
  }

每次組件庫代碼更改后,在組件庫進(jìn)行npm run build構(gòu)建,這里同樣會面臨像npm link那樣的尷尬處境,項目會去組件庫找組件的自身依賴,如果沒有找到則會啟動錯誤,所以組件庫每次構(gòu)建完你都需要在項目重新執(zhí)行npm install安裝組件庫的自身依賴。

調(diào)試完畢提交代碼及上線前需要手動把package.json更新回正確的依賴包地址。

整個調(diào)試流程如下圖。

image.png

操作成本:

  • 每次組件庫修改需要build構(gòu)建

  • 項目重新執(zhí)行npm install

  • 結(jié)束調(diào)試后重新安裝正確的生產(chǎn)依賴包

  • 上線前需要手動修改package.json的正確依賴包地址

適用場景:
組件庫自身沒有依賴的簡單情況下

3. 復(fù)制組件庫產(chǎn)物到項目庫node_modules下

在組件庫構(gòu)建后,將dist下的構(gòu)建產(chǎn)物復(fù)制到項目 node_modules 的@cute/hello目錄下,組件庫下執(zhí)行命令:

cp -r dist /Users/user/my-project/node_modules/@cute/hello

每次組件庫代碼更改后,都需要在組件庫進(jìn)行npm run build操作,而且項目的node_modules下組件庫復(fù)制完可能不會觸發(fā)熱更新,需要刪掉項目下組件庫再執(zhí)行cp命令,那么命令改成先刪除再復(fù)制,這樣就可觸發(fā)項目的熱更新了。

rm -rf /Users/user/my-project/node_modules/cute/hello && cp -r dist /Users/user/my-project/node_modules/@cute/hello

整個調(diào)試流程如下圖。

image.png

操作成本:

  • 每次組件庫修改需要build構(gòu)建

  • 每次需要在組件庫執(zhí)行cp命令

  • 結(jié)束調(diào)試后重新安裝正確的生產(chǎn)依賴包

  • 只需要在組件庫下執(zhí)行一些操作命令,項目庫無額外操作成本

適用場景:

  • 基本都能適用

自動化調(diào)試流程:nodemon+yalc

自動化調(diào)試流程依賴【文件監(jiān)控開源庫 nodemon】和【本地依賴管理開源庫 yalc】,大致思路是用nodemon監(jiān)聽文件修改,然后自動執(zhí)行組件庫打包,再使用yalc進(jìn)行組件庫發(fā)布。

nodemon 是一個用來監(jiān)視應(yīng)用程序中文件更改并自動重啟服務(wù)的開源庫,僅用于開發(fā)環(huán)境(推薦),他不影響項目代碼,可以理解為是把node替換成nodemon執(zhí)行命令。

yalc 是一個類似于本地化 npm 的解決方案,它在本地環(huán)境中創(chuàng)建了一個共享的 library 存儲庫( ~/.yalc ),當(dāng)你需要本地依賴時可以快速從存儲庫中拉取資源進(jìn)行使用。它與 npm link 不同就是 npm link 中組件庫和項目引用的依賴是映射到一個地方的,當(dāng)項目庫啟動時會在依賴下去尋找其他依賴,如果找不到相關(guān)依賴,應(yīng)用就會異常;如果組件庫的編譯規(guī)則和項目的編譯規(guī)則不匹配,也同樣會出問題。而 yalc 就是相當(dāng)于將文件復(fù)制進(jìn)依賴目錄從而能正常運(yùn)行。


image.png

更多詳情可以看以下鏈接

● yalc: https://github.com/whitecolor/yalc

● nodemon: https://github.com/remy/nodemon

自動化流程

自動化流程通過使用nodemon監(jiān)聽文件修改后,自動執(zhí)行組件庫打包,再使用 yalc push 進(jìn)行組件庫發(fā)布,項目只要 yalc add [package] 后,后續(xù)就能直接熱更新下預(yù)覽變更了。具體實(shí)現(xiàn)流程下面會介紹。

image.png

首先,全局安裝nodemon和yalc:

npm install -g yalc  // 全局安裝
npm install -D nodemon // 組件庫安裝
// 或
yarn global add yalc
yarn global add nodemon -D

組件庫單獨(dú)執(zhí)行 yalc publish 時會把當(dāng)前組件庫下相關(guān)文件存儲到本地共享的全局存儲中,除了不會發(fā)布到真實(shí)遠(yuǎn)端倉庫外,都和npm真實(shí)發(fā)包無異。更好用的是 yalc publish --push 或者簡稱 yalc push ,它會將你的依賴發(fā)布到本地存儲庫(更新狀態(tài)),并將所有更改傳播到現(xiàn)有通過 yalc 安裝的依賴中,下面會用到。

dist git:(xxx) ? yalc push
@cute/hello@2.0.0-beta.2 published in store.

在組件庫的 package.json 中添加 nodemon 腳本命令,這里可以新建一個 nodemon.json 的配置文件去配置詳細(xì)的信息(具體配置可以去官網(wǎng)查看)。nodemon 啟動監(jiān)聽,當(dāng)監(jiān)聽文件變化時自動 build 構(gòu)建,并將庫 yalc push 發(fā)布到緩存中。

如果當(dāng)前構(gòu)建后,package.json 中 private: true 時,直接 yalc push 會報錯:Will not publish package with private: true use --private flag to force publishing. 需要使用 yalc push --private 強(qiáng)制發(fā)布。

{
    "scripts": {
        "build": "node scripts/dist.js",
        "build:watch": "nodemon --config 'nodemon.json' -x 'npm run build && cd dist && yalc push --private'"
    },
}
// nodemon.json
{
  "restartable": "rs",
  "ignore": [
    ".git",
    "node_modules/**/node_modules",
    "package.json",
    "nodemon.json",
    "dist",
  ],
  "verbose": true,
  "execMap": {
    "js": "node --harmony"
  },
  "events": {
    "restart": "osascript -e 'display notification \"App restarted due to:\n'$FILENAME'\" with title \"nodemon\"'"
  },
  "watch": ["src"],
  "env": {
    "NODE_ENV": "development"
  },
  "ext": "js,json,css,scss,vue"
}

上面組件庫的準(zhǔn)備工作完成后,項目下只要執(zhí)行 yalc add @cute/hello ,在項目根目錄下就會自動生成一個 yalc.lock 文件和 .yalc 目錄,.yalc 目錄類似 node_modules 那樣,它存放著從存儲庫中拉取下來的依賴,yalc.lock 記錄當(dāng)前被替換的組件庫版本信息,這些信息用來后面還原依賴包用。同時 my-projecy 中的 node_modules 的組件庫也被替換成 yalc 緩存中的組件庫了。

my-project git:(xxx) yalc add @cute/hello
Package @cute/hello@2.0.0-beta.2 added ==> /Users/user/my-project/node_modules/@cute/hello

package.json的組件庫地址自動注入了 file:.yalc/@cute/hello 。

"dependencies": {
    "@cute/hello": "file:.yalc/@cute/hello",
}

項目根目錄下自動生成了 yalc.lock 文件和 .yalc 目錄:

# yalc.lock
{
  "version": "v1",
  "packages": {
    "@cute/hello": {
      "signature": "519aa4086b04e080b8d9731188dd162d",
      "file": true,
      "replaced": "@cute/hello@2.0.0-beta.1"
    }
  }
}
image.png

此時,就可以快樂地進(jìn)行組件庫和項目庫之間的調(diào)試了,不需要額外的操作成本,所改代碼即所視。

調(diào)試完畢后,要提交代碼部署到公測環(huán)境時,執(zhí)行 yalc remove --all(如果只引了一個依賴包也可直接 yalc remove [package],yalc remove --all 會將當(dāng)前所有從 yalc 存儲中拉取的都還原),即可一鍵還原安裝包現(xiàn)場,上面說到的package.json會自動還原了依賴包版本、.yalc、yalc/lock都自動去掉了,還原了開發(fā)調(diào)試前的現(xiàn)場,但是node_modules中的對應(yīng)的組件庫也去掉了,所以完成調(diào)試后本地只需要重新npm install安裝正常版本即可后續(xù)開發(fā)。

? my-project git:(xxx) ? yalc remove --all
Removing installation of @cute/hello in /Users/user/my-project

總結(jié)

總結(jié)一下,自動化調(diào)試流程就是在組件庫使用nodemon監(jiān)聽文件變更后,自動執(zhí)行 build 構(gòu)建和 yalc push,項目中通過 yalc add [package] 從本地存儲中拉取依賴包進(jìn)行調(diào)試,調(diào)試完成后 yalc remove --all 一鍵恢復(fù)調(diào)試前現(xiàn)場。

其實(shí)以往的調(diào)試方式都可以加 nodemon 命令去監(jiān)聽達(dá)到自動化調(diào)試的目的,但是卻有一些局限性(如下表),縱觀來看 yalc 的方式更加通用且邏輯清晰,組件庫和項目庫不需要花太多時間去理會中間的執(zhí)行過程,只需要像 npm 安裝依賴一樣,在項目中通過 yalc 引入多個組件庫進(jìn)行調(diào)試,調(diào)試完畢后 yalc remove --all 即可清除所有調(diào)試庫。

調(diào)試方式 \ 對比 nodemon改造 局限
npm link 組件庫nodemon監(jiān)聽文件變化->build構(gòu)建->npm link 項目需要重啟服務(wù);編譯規(guī)則不匹配,也可能會出問題
cp復(fù)制構(gòu)建產(chǎn)物 組件庫nodemon監(jiān)聽文件變化->build構(gòu)建->scripts中添加cp命令 如果有多個項目在用組件庫,需要寫多套cp命令調(diào)試
修改package.json依賴庫地址 組件庫nodemon監(jiān)聽文件變化->build構(gòu)建->自動進(jìn)入項目庫執(zhí)行npm install 項目庫每次install很繁瑣,調(diào)試完成后項目的依賴地址需要手動恢復(fù),這樣一點(diǎn)也不cool

更多閱讀

● npm link:https://docs.npmjs.com/cli/v8/commands/npm-link

● yalc: https://github.com/whitecolor/yalc

● nodemon: https://github.com/remy/nodemon

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容