npm install及其目錄結構


  npm install 安裝包及其依賴。npm install: 默認情況下,安裝package.json文件中列出的所有依賴。加-P或--production后,只安裝dependencies列出的依賴,而不安裝devDependencies列出的依賴。npm install [<@scope>/]<name>,安裝包的最新版本,並記錄在package.json中的dependencies中,加-D或--save-dev,安裝包,並記錄到devDependencies 中

npm install react
npm install @babel/core -D

  npm install [<@scope>/]<name>@<version>:  安裝指定版本的包

npm install react@16

   npm install 安裝依賴到什么地方呢?默認情況下,它會安裝到當前包的根目錄下的node_modules中。比如redux,它有自己的依賴,安裝redux時,它的依賴就會安裝redux的根目錄下的node_modules中。

   如果安裝依賴的地方並不在一個包下,比如,開始一個新項目,要安裝依賴,它只是一個普通的目錄,那就安裝到當前目錄下的node_modules中。如果安裝的依賴有scope,比如@babel/core, 它會安裝到node_modules下的@scope目錄下,相同的scope的包集中放到同一個目錄下。安裝完成后,可以通過require("packagename")來加載主模塊(packae.json中main指定的文件),或 require("packagename/lib/path/to/sub/module") 加載其它模塊。如果安裝包的是命令包,比如webpack-cli,它里面的bin目錄會鏈接到node_modules中的./bin目錄下,當在package.json中的script寫命令,然后使用npm run 執行時,npm 會找到相應的命令執行。其實,這里有一個小細節,當在一個目錄中安裝包時,npm會從當前目錄向上查找,看有沒有一個目錄包含package.json文件或node_modules目錄,如果有,它會在找到的目錄中安包,npm認為這是一個有意義的目錄。如果沒有,則在當前目錄安裝包。比如項目根目錄下,有packag.json, 你不小心 cd src中,此時在src目錄下安裝包,npm還是會把包安裝到根目錄。npm 安裝包的時候,先安裝到npm 的緩存中,然后再解壓到node_modules中。

  項目的依賴都安裝到node_modules下,那node_modules的目錄結構是怎么樣的? npm 2版本的時候,以嵌套的方式安裝所有依賴,比如App項目依賴A,A依賴B,那么App的node_modules中有A, A的node_modules中的B。這就會導致依賴樹太深,並且安裝的包大多,冗余。為了解決這個問題,npm 3版本則試圖扁平化安裝。主依賴和二級依賴安裝到同級目錄,主依賴就是package.json中列出的依賴,二級依賴就是主依賴的依賴。還是以項目App為例,主依賴就是A,二級依賴就是B,npm 3安裝的時候,A和B在同一級目錄,都是在App的node_modules中。

   項目開發時,又安裝了一個依賴C,C也依賴B,不過是2.0版本,如果是npm2安裝,直接安裝C依賴,C里面嵌套B。如果是npm3安裝,它就是安裝C,然后嘗試把B安裝到C同等級別的目錄,也就node_modules頂級目錄,但node_modules頂級目錄下面已經有了B 1.0依賴,不能再安裝B 2.0依賴,否則就沖突了,所以B2.0,只能安裝到C目錄下

   在命令行窗口,它會如下顯示

  你會發現,目錄結構沒有辦法顯示依賴關系, 可以使用npm ls 命令,列出依賴及其關系,列出主依賴,則是 npm ls --depth=0

  假設再安裝依賴D,它也依賴Bv2.0,還是由於node_modules頂級目錄中安裝了B1.0, B2.0要安裝到D下面,注意,這里和以后的安裝都是npm3 了,

  繼續依賴E,E依賴B1.0,此時只安裝E依賴,B依賴不用裝了,因為在頂級目錄中已經有了,

   反應到命令行中就是

   現在升級A 到2.0,正好它也依賴B2.0,首先是package.json 中A依賴的版本號從1.0 到2.0, 再在node_module中,刪除掉A1.0,安裝2.0,不能刪除B1.0 因為E在用,最后安裝B2.0

 

 

   現在package.json中的依賴如下

"dependencies": {
    "mod-a": "^2.0.0",
    "mod-c": "^1.0.0",
    "mod-d": "^1.0.0",
    "mod-e": "^1.0.0"
}

  此時,你覺得項目初始化完成了,就提交了。同事拿到新代碼,就npm install,安裝所有依賴,你會發現他安裝的目錄如下

 

 

   安裝順序起起到到了重要的作用,npm install 先安裝A2.0, 它依賴B2.0, 所以在node_modules頂級目錄中安裝了A2.0和B2.0,由於C和D都是依賴B2.0, 所以只在node_modules中安裝C和D主依賴就可以了,B2.0已經存在了,安裝E的時候,它由於依賴B1.0,所以在它的node_modules下面安裝了B1.0.

  當npm install 一個依賴的時候,它會從當前目錄向上找,如果在祖先node_modules中找到符合的依賴,它就不會在本目錄下安裝,這也解決了循環依賴問題。但你會發現,你和你的同事的node_modules目錄結構不一致了。npm3 這種安裝依賴的方式,會導致一個問題,你的機器上的node_modules可能和你同事的node_modules 不一致,npm3 並不會已確定性的方式安裝node_modules。如果項目中只依賴主依賴,那是沒有影響的,如果有使用二級依賴,那就會有影響。比如 import {} from B, 你同事引用是B2.0, 而你引用的是B1.0. 怎么辦?把node_modules刪除了,重新安裝。這也導致package-lock.json 文件出現。如果一個項目中有package-lock.json文件,npm install的時候,就會照package-lock.json文件列出的依賴樹安裝依賴,package-lock.json文件會記錄項目開發時,依賴的安裝順序。比如A從1.0升級到2.0,package.json中只會把A升級到2.0,但package-lock.json 則會記錄

{
    "dependencies": {
        "A": {
            "version": "2.0.0",
            "requires": {
                "B": "2.0.0"
            },

            "dependencies": {
                "B": {
                    "version": "2.0.0"
                }
            }
        },

        "B": {
            "version": "1.0.0",
        },

        "E": {

            "version": "1.0.0",

            "requires": {

                "B": "1.0.0",

            }
        }
    }
}

  可以清新地看到安裝順序,無論以后,誰按照package-lock.json文件安裝,安裝的目錄都是一樣的。

  后面又出了yarn, yarn.lock文件,安裝包的依賴時,如果包中有package-lock.json或shrinkwrap.json或yarn.lock這些文件, 它會以這些文件為依據,安裝依賴。參考順序是npm-shrinkwrap.json,package-lock.json,yarn.lock。

  在上圖的基礎上,假設你現在繼續開發,把E升級了,它依賴B2.0,npm 會刪除掉E1.0,安裝E2.0,刪除掉B1.0,因為沒有模塊依賴它了,安裝B2.0 到node_module頂級目錄。

   這時,又有一個問題,模塊B2.0 在每一個目錄中,為了移除冗余,可以使用 npm deque,  這個命令找到依賴B2.0的模塊,然后,重定向到頂級目錄中的依賴,然后刪掉嵌套的依賴b2.0

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM