前言
大家好,我是林三心, 用最通俗易懂的話講最難的知識點 是我的座右銘, 基礎是進階的前提 是我的初心。
幽靈依賴?
前幾天在公司的技術分享會上,我總是聽到大佬們在提起一個名詞—— 幽靈依賴 ,起初我沒有太在意,以為這個不太重要,所以就沒怎麽去了解這個名詞。
直到我在做計畫
pnpm遷移
的時候,我突然很想知道它跟
幽靈依賴
到底有什麽關系呢?
其實在了解什麽關系之前,我應該去了解一下什麽是 幽靈依賴 ,我們接著聊!!!
什麽是幽靈依賴?
比如我現在,我在開發一個計畫A,計畫A中我裝了
npm-lsx
這個包,而這個
npm-lsx
的包依賴了
npm-test
,咱們來看看這兩處
packages.json
依賴關系是:A <- npm-lsx <- npm-test
// A/packages.json
{
"name": "A",
"dependencies": {
"npm-lsx": "^1.0.0"
}
}
// A/node_modules/npm-lsx/packages.json
{
"name": "npm-lsx",
"dependencies": {
"npm-test": "^1.0.0"
}
}
node_modules規則
如果按照
node_modules
的規則的話,那麽目錄的結構應該是這樣的
node_modules
├── npm-lsx
| └── node_modules
| └── npm-test
但是如果依賴關系很長的話,那麽會導致目錄深度非常深,所以我們常用的
npm、yarn
解決了這個問題
npm、yarn
它們是怎麽解決這個問題的呢?
npm、yarn
為了解決依賴關系過長時,導致的目錄結構過深,采用了
扁平化
,也就是所有依賴都被拍平到
node_modules
目錄下。這樣的好處就是,不再有層級過深的問題。
現在目錄結構變成這樣了
// A/node_modules
node_modules
├── npm-lsx
├── npm-test
幽靈依賴
接著上面的範例,繼續聊,請看下面的程式碼
const lsx = require('npm-lsx')
const test = require('npm-test')
lsx()
test()
你們覺得這段程式碼有問題嗎?其實執行起來是沒問題的。但是問題來了,我們計畫中居然能直接參照
npm-test
這個包!!!
我們都知道依賴關系是:
A <- npm-lsx <- npm-test
按理說,
A
是不能直接參照
npm-test
的,因為沒有直接依賴關系啊!!!但是因為前面說了,
npm、yarn
會將依賴拍平在
A的node_modules
中,這導致了
A
可以直接
require('npm-test')
我們稱這個
npm-test
為
幽靈依賴
!!!
幽靈依賴的壞處?
某天 npm-lsx 不依賴 npm-test 了
已知你現在程式碼是這樣
const lsx = require('npm-lsx')
const test = require('npm-test')
lsx()
test()
某天
npm-lsx
升級了!它不再依賴
npm-test
了!那麽此時
A
的
node-modules
中變了!
// 以前
node_modules
├── npm-lsx
├── npm-test
// 現在
node_modules
├── npm-lsx
那麽你的程式碼會報錯!
const lsx = require('npm-lsx')
const test = require('npm-test') // 沒有
lsx()
test() // 報錯!!!
其實這個情況還好,因為這種情況在打包上線過程中就會報錯依賴找不到了,所以不太會造成線上的報錯崩潰
多計畫參照同一個幽靈依賴
我現在有兩個計畫 A 和 B
A
中的
node_modules
目錄為,現階段
npm-test
的版本為
1.0.0
// A/node_modules
node_modules
├── npm-lsx
├── npm-test 版本號:1.0.0
A 中某個檔的程式碼為
const test = require('npm-test')
test()
B 中某個檔的程式碼為
const test = require('npm-test')
test()
當有一天
npm-lsx
所依賴的
npm-test
升級了!版本升級為了
2.0.0
// A/node_modules
node_modules
├── npm-lsx
├── npm-test 版本號:2.0.0
此時
test
的用法也變了~而因為
A
計畫已經回歸過了,所以他知道,也改了對應的程式碼
const test = require('npm-test')
test.run() // 修改程式碼
而 B 計畫就沒那麽好運了,它並沒有進行回歸,所以並沒有去改程式碼!!!!
const test = require('npm-test') // 有
test() // 直接報錯
這就慘了,
B
計畫在打包階段並不會因為依賴不到
npm-test
而報錯,所以它會順利上線。。然後,等到了線上執行起來,直接報錯!!!這是非常嚴重的的事故!
結語
點個【贊】和【在看】是對林三心最大的鼓勵,林三心會非常開心的~~~
關註公眾號【前端之神】,回復【加群】,即可獲得加入【千人前端學習大群】的方式,交流找工作,摸魚,吹水~