自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

實(shí)現(xiàn)一個(gè)簡(jiǎn)易的 Npm Install 你會(huì)了嗎?

開(kāi)發(fā) 前端
現(xiàn)在寫(xiě)代碼我們一般不會(huì)全部自己實(shí)現(xiàn),更多是基于第三方的包來(lái)進(jìn)行開(kāi)發(fā),這體現(xiàn)在目錄上就是 src 和 node_modules 目錄。

 [[400477]]

本文轉(zhuǎn)載自微信公眾號(hào)「神光的編程秘籍」,作者神說(shuō)要有光zxg。轉(zhuǎn)載本文請(qǐng)聯(lián)系神光的編程秘籍公眾號(hào)。

現(xiàn)在寫(xiě)代碼我們一般不會(huì)全部自己實(shí)現(xiàn),更多是基于第三方的包來(lái)進(jìn)行開(kāi)發(fā),這體現(xiàn)在目錄上就是 src 和 node_modules 目錄。

src 和 node_modules(第三方包) 的比例不同項(xiàng)目不一樣。

運(yùn)行時(shí)查找第三方包的方式也不一樣:

  • 在 node 環(huán)境里面,運(yùn)行時(shí)就支持 node_modules 的查找。所以只需要部署 src 部分,然后安裝相關(guān)的依賴。

  • 在瀏覽器環(huán)境里面不支持 node_modules,需要把它們打包成瀏覽器支持的形式。

跨端環(huán)境下,它是上面哪一種呢?

都不是,不同跨端引擎的實(shí)現(xiàn)會(huì)有不同,跨端引擎會(huì)實(shí)現(xiàn) require,可以運(yùn)行時(shí)查找模塊(內(nèi)置的和第三方的),但是不是 node 的查找方式,是自己的一套。

和 node 環(huán)境下的模塊查找類似,但是目錄結(jié)構(gòu)不一樣,所以需要自己實(shí)現(xiàn) xxx install。

思路分析

npm 是有自己的 registry server 來(lái)支持 release 的包的下載,下載時(shí)是從 registry server 上下載。我們自己實(shí)現(xiàn)的話沒(méi)必要實(shí)現(xiàn)這一套,直接用 git clone 從 gitlab 上下載源碼即可。

依賴分析

要實(shí)現(xiàn)下載就要先確定哪些要下載,確定依賴的方式和打包工具不同:

  • 打包工具通過(guò) AST 分析文件內(nèi)容確定依賴關(guān)系,進(jìn)行打包
  • 依賴安裝工具通過(guò)用戶聲明的依賴文件 (package.json / bundle.json)來(lái)確定依賴關(guān)系,進(jìn)行安裝

這里我們把包的描述文件叫做 bundle.json,其中聲明依賴的包:

  1.     "name""xxx"
  2.     "dependencies": { 
  3.         "yyyy""aaaa/bbbb#release/1111" 
  4.     } 

通過(guò)分析項(xiàng)目根目錄的 bundle.json 作為入口,下載每一個(gè)依賴,分析 bundle.json,然后繼續(xù)下載每一個(gè)依賴項(xiàng),遞歸這個(gè)過(guò)程。這就是依賴分析的過(guò)程。

這樣依賴分析的過(guò)程中進(jìn)行包的下載,依賴分析結(jié)束,包的下載也就結(jié)束了。這是一種可行的思路。

但是這種思路存在問(wèn)題,比如:版本沖突怎么辦?循環(huán)依賴怎么辦?

解決版本沖突

版本沖突是多個(gè)包依賴了同一個(gè)包,但是依賴的版本不同,這時(shí)候就要選擇一個(gè)版本來(lái)安裝,我們可以簡(jiǎn)單的把規(guī)則定為使用高版本的那個(gè)。

解決循環(huán)依賴

包之間是可能有循環(huán)依賴的(這也是為什么叫做依賴圖,而不是依賴樹(shù)),這種問(wèn)題的解決方式就是記錄下處理過(guò)的包,如果同個(gè)版本的包被分析過(guò),那么久不再進(jìn)行分析,直接拿緩存。

這種思路是解決循環(huán)依賴問(wèn)題的通用思路。

我們解決了版本沖突和循環(huán)依賴的問(wèn)題,還有沒(méi)有別的問(wèn)題?

版本沖突時(shí)會(huì)下載版本最高的包,但是這時(shí)候之前的低版本的包已經(jīng)下載過(guò)了,那么就多了沒(méi)必要的下載,能不能把這部分冗余下載去掉。

依賴分析和下載分離

多下載了一些低版本的包的原因是我們?cè)谝蕾嚪治龅倪^(guò)程中進(jìn)行了下載,那么能不能依賴分析的時(shí)候只下載 bundle.json 來(lái)做分析,分析完確定了依賴圖之后再去批量下載依賴?

從 gitlab 上只下載 bundle.json 這一個(gè)文件需要通過(guò) ssh 協(xié)議來(lái)下載,略微復(fù)雜,我們可以用一種更簡(jiǎn)單的思路來(lái)實(shí)現(xiàn):

  1. git clone --depth=1 --branch=bb xxx 

加上 --depth 以后 git clone 只會(huì)下載單個(gè) commit,速度會(huì)很快,雖然比不上只下載 bundle.json,但是也是可用的(我試過(guò)下載全部 commit 要 20s 的時(shí)候,下載單個(gè) commit 只要 1s)。

這樣我們?cè)谝蕾嚪治龅臅r(shí)候只下載一個(gè) commit 到臨時(shí)目錄,分析依賴、解決沖突,確定了依賴圖之后,再去批量下載,這時(shí)候用 git clone 下載全部的 commit。最后要把臨時(shí)目錄刪除。

這樣,通過(guò)分離依賴分析和下載,我們?nèi)サ袅藳](méi)必要的一些低版本包的下載。下載速度會(huì)得到一些提升。

全局緩存

當(dāng)本地有多個(gè)項(xiàng)目的時(shí)候,每個(gè)項(xiàng)目都是獨(dú)立下載自己的依賴包的,這樣對(duì)于一些公用的包會(huì)存在重復(fù)下載,解決方式是全局緩存。

分析完依賴進(jìn)行下載每一個(gè)依賴包的時(shí)候,首先查找全局有沒(méi)有這個(gè)包,如果有的話,直接復(fù)制過(guò)來(lái),拉取下最新代碼。如果沒(méi)有的話,先下載到全局,然后復(fù)制到本地目錄。

通過(guò)多了一層全局緩存,我們實(shí)現(xiàn)了跨項(xiàng)目的依賴包復(fù)用。

代碼實(shí)現(xiàn)

為了思路更清晰,下面會(huì)寫(xiě)偽代碼

依賴分析

依賴分析會(huì)遞歸處理 bundle.json,分析依賴并下載到臨時(shí)目錄,記錄分析出的依賴。會(huì)解決版本沖突、循環(huán)依賴問(wèn)題。

  1. const allDeps = {}; 
  2. function installDeps(projectDir) { 
  3.     const bundleJsonPath = path.resolve(projectDir, 'bundle.json'); 
  4.     const bundleInfo = JSON.parse(fs.readFileSync(bundleJsonPath)); 
  5.      
  6.     const bundleDeps = bundleInfo.dependencies; 
  7.     for (let depName in bundleDeps) { 
  8.         if(allDeps[depName]) { 
  9.             if (allDeps[depName] 和 bundleDeps[depName] 分支和版本一樣) { 
  10.                 continue;// 跳過(guò)安裝 
  11.             } 
  12.             if (allDeps[depName] 和 bundleDeps[depName] 分支和版本不一樣){ 
  13.                 if (bundleDeps[depName] 版本 < allDeps[depName] 版本 ) { 
  14.                     continue
  15.                 } else { 
  16.                     // 記錄下版本沖突 
  17.                     allDeps[depName].conflit = true
  18.                 } 
  19.             
  20.             } 
  21.         } 
  22.         childProcess.exec(`git clone --depth=1 ${臨時(shí)目錄/depName}`); 
  23.         allDeps[depName] = { 
  24.             name: depName 
  25.             url: xxx 
  26.             branch: xxx 
  27.             version: xxx 
  28.         } 
  29.         installDeps(`${臨時(shí)目錄/depName}`); 
  30.     }     

下載

下載會(huì)基于上面分析出的 allDeps 批量下載依賴,首先下載到全局緩存目錄,然后復(fù)制到本地。

  1. function batchInstall(allDeps) { 
  2.     allDeps.forEach(dep => { 
  3.         const 全局目錄 = path.resolve(os.homedir(), '.xxx'); 
  4.         if (全局目錄/dep.name 存在) { 
  5.             // 復(fù)制到本地 
  6.             childProcess.exec(`cp 全局目錄/dep.name 本地目錄/dep.name`); 
  7.         } else { 
  8.             // 下載到全局 
  9.             childProcess.exec(`git clone --depth=1 ${全局目錄/dep.name}`); 
  10.              // 復(fù)制到本地 
  11.             childProcess.exec(`cp 全局目錄/dep.name 本地目錄/dep.name`); 
  12.         } 
  13.     }); 

這樣,我們就完成了依賴的分析和下載,實(shí)現(xiàn)了全局緩存。

總結(jié)

我們首先梳理了不同環(huán)境(瀏覽器、node、跨端引擎)對(duì)于第三方包的處理方式不同,瀏覽器需要打包,node 是運(yùn)行時(shí)查找,跨端引擎也是運(yùn)行時(shí)查找,但是用自己實(shí)現(xiàn)的一套機(jī)制。

然后明確了打包工具確定依賴的方式是 AST 分析,而依賴下載工具則是基于包描述文件 bundl.json(package.json) 來(lái)分析。然后我們實(shí)現(xiàn)了遞歸的依賴分析,解決了版本沖突、循環(huán)依賴問(wèn)題。

為了減少?zèng)]必要的下載,我們做了依賴分析和下載的分離,依賴分析階段只下載單個(gè) commit,后續(xù)批量下載的時(shí)候才全部下載。下載方式?jīng)]有實(shí)現(xiàn) registry 的那套,而是直接從 gitlab 來(lái) git clone。

為了避免多個(gè)項(xiàng)目的公共依賴的重復(fù)下載,我們實(shí)現(xiàn)了全局緩存,先下載到全局目錄,然后再?gòu)?fù)制到本地。

npm install、yarn install 的實(shí)現(xiàn)流程細(xì)節(jié)會(huì)更多一些,但是整體流程類似。希望這篇文章能幫你梳理清楚思路:不同環(huán)境是怎么處理第三方包的,xxx install 的依賴分析和下載的流程是什么樣的。

 

責(zé)任編輯:武曉燕 來(lái)源: 神光的編程秘籍
相關(guān)推薦

2022-09-19 08:01:45

數(shù)據(jù)庫(kù)SQLitePostgreSQL

2023-03-26 22:02:53

APMPR監(jiān)控

2021-09-03 05:03:58

模塊命令項(xiàng)目

2023-09-19 08:03:50

rebase?merge

2023-04-27 08:42:50

效果

2021-10-04 09:29:41

對(duì)象池線程池

2024-06-21 08:15:25

2024-06-19 09:47:21

2022-02-08 09:09:45

智能指針C++

2024-04-01 08:13:59

排行榜MySQL持久化

2023-07-10 07:17:29

無(wú)效化空窗口

2022-06-16 07:50:35

數(shù)據(jù)結(jié)構(gòu)鏈表

2025-04-01 03:25:00

2023-11-27 07:33:55

2022-04-26 10:47:53

分配權(quán)限vuejs

2023-12-07 12:29:49

Nginx負(fù)載均衡策略

2024-03-12 08:37:32

asyncawaitJavaScript

2024-07-29 10:35:44

KubernetesCSI存儲(chǔ)

2024-10-16 10:41:36

2024-11-28 10:32:32

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)