如何快速入門VUE3.0:進入學習
說到前端開發,就一定離不開npm
,作為前端包管理的老大,npm
是我們必須知道的一個東西。
雖然每天都用npm
安裝包,但是你們對package.json
和package-lock.json
這兩個檔案又瞭解多少呢?今天筆者就來詳細分析下這兩個檔案,希望能對大家有所幫助。
在說package.json
和package-lock.json
之前,我們先來說說npm安裝包的方式
和npm的安裝流程
。
npm
安裝包的方式分為本地安裝和全域性安裝。安裝使用npm install
或簡寫形式npm i
。
本地安裝的包只能在當前目錄下使用。
本地安裝很簡單,以element-ui
為例
npm i element-ui
在實際專案開發過程中,本地安裝我們都會先生成package.json
檔案。然後安裝的時候包的版本會自動記錄在該檔案中。
本地安裝的包又分為開發依賴(devDependencies)
和生產依賴(dependencies)
。
對於一些只會在開發環境中用到的包我們可以安裝在開發依賴(devDependencies)
中。比如webpack、vite
等等。
對於一些會在生產環境中用到的包我們可以安裝在生產依賴(dependencies)
中。比如element-ui
等等。
那麼怎麼讓安裝的包分別放到對應的依賴位置呢?
如果想要安裝的包放在開發依賴(devDependencies)
中,我們傳遞引數 --save-dev
或 -D
即可。
如果想要安裝的包放在生產依賴(dependencies)
中,我們傳遞引數 --save
或 -S
即可。
注意如果我們沒傳遞依賴引數。會把包預設安裝到生產依賴
(dependencies)
中
全域性安裝的包能在當本機所有目錄下使用。我們在安裝包的時候傳遞引數-g
或--global
即可。
npm i -g element-ui npm i --global element-ui
全域性安裝的包路徑我們可以通過npm config get prefix
檢視。
前面我們只是介紹了 npm install
是用來安裝依賴的,下面再講一下它到底是怎麼安裝的以及一些具體的安裝細節。
執行安裝命令之後,npm 首先會去查詢 npm 的設定資訊。 其中,我們最熟悉的就是安裝時候的源資訊。npm 會在專案中查詢是否有 .npmrc
檔案,沒有的話會再檢查全域性設定的 .npmrc
,還沒有的話就會使用 npm 內建的 .npmrc
檔案。
獲取完組態檔之後,就會構建依賴樹。首先會檢查下專案中是否有 package-lock.json
?檔案:存在 lock 檔案的話,會判斷 lock 檔案和 package.json
中使用的依賴版本是否一致,如果一致的話就使用 lock 中的資訊,反之就會使用 npm 中的資訊;那如果沒有 lock 檔案的話,就會直接使用 package.json
中的資訊生成依賴樹。
在有了依賴樹之後,就可以根據依賴樹下載完整的依賴資源。在下載之前,會先檢查下是否有快取資源,如果存在快取資源的話,那麼直接將快取資源解壓到 node_modules
中。如果沒有快取資源,那麼會先將 npm 遠端倉庫中的包下載至本地,然後會進行包的完整性校驗,校驗通過後將其新增的快取中並解壓到 node_modules
中。
package-lock.json
檔案生成 package-lock.json
檔案。 這個檔案主要是用來鎖定包的版本,這個筆者後面會詳細說。
接下來我們說說 package.json
和package-lock.json
生成方式
package.json
和package-lock.json
生成方式首先要明確一點,package.json
不會自動生成,需要我們使用命令建立。package-lock.json
是自動生成的,我們使用 npm install
安裝包後就會自動生成。
下面我們介紹下怎麼建立package.json
。
npm
為我們提供了建立 package.json
檔案的命令 npm init
,執行該命令會問幾個基本問題,如包名稱、版本號、作者資訊、入口檔案、倉庫地址、關鍵字、描述、許可協定等,多數問題已經提供了預設值,你可以在問題後敲回車接受預設值。
基本問題問完之後 npm
會在生成檔案之前把 package.json
檔案內容打出來供你確認,點選enter
鍵就會生成package.json
檔案。
如果覺得這樣一步一步太慢的話我們還可以一鍵生成。使用npm init -y
或者 npm init -f
就可以一鍵生成package.json
檔案啦。(npm init -y
和 npm init -f
是npm init --yes
和 npm init --force
的簡寫形式)。
到這裡,小夥伴們肯定有疑問了,一鍵生成的package.json
裡面的內容是在哪裡控制的呢?比如我想一鍵生成出來的package.json
裡面的author
是我自己需要怎麼做呢?
我們來看看npm的初始設定吧,使用npm config ls -l
命令檢視npm
的所有設定。
可以發現我們的init-author-name
的設定是空,所以我們來設定下。
# 設定設定 npm config set init-author-name 'randy' # 檢視設定 npm config get init-author-name
我們再來生成一遍package.json
可以發現,我們的author
就有預設值啦,其他的預設設定都可以設定,這裡筆者就不再舉例了。
package.json
檔案,它是專案的組態檔,常見的設定有設定專案啟動、打包命令,宣告依賴包等。package.json
檔案是一個JSON
物件,該物件的每一個成員就是當前專案的一項設定。
下面筆者分別介紹各個設定代表的意義。
name
很容易理解,就是專案的名稱。
version
欄位表示該專案包的版本號,它是一個字串。在每次專案改動後,即將釋出時,都要同步的去更改專案的版本號。
npm
預設所有的Node
包都使用語意化版本號,這是一套指導開發人員如何增長版本號的規則。
每個版本號都形如:1.2.3
,有三部分組成,依次叫主版本號
、次版本號
、修訂號
;
當新版本無法相容基於前一版本的程式碼時,則提高主版本號;
當新版本新增了功能和特性,但仍相容前一版本的程式碼時,則提高次版本號;
當新版本僅僅修正了漏洞或者增強了效率,仍然相容前一版本程式碼,則提高修訂號;
預設情況下,npm install xxx --save
下載的都是最新版本,並且會在package.json
檔案裡登記一個最優版本號。
舉個例子,我們安裝element-ui
npm i element-ui -S
在安裝的時候它會選擇目前的一個最新的版本進行安裝,我們檢視github
,看到element-ui
的最新版本是2.15.9
。
這裡我們自動安裝的也就是2.15.9
版本,並且版本號並不是固定的而是一個最優版本。
那什麼是最優版本呢?
最優版本會在版本前多了一個^
符號,這個符號其實是有特殊意義的。同理這個符號還有可能是~
符號。
那這兩個符號有什麼區別呢?
^
意味著下載的包可能會是更高的次版本號或者修訂版本號。(也就是主版本不能變,次版本、修訂版本可以隨意變)。
相容某個大版本 如:^1.1.2 ,表示>=1.1.2 <2.0.0,可以是1.1.2,1.1.3,.....,1.1.n,1.2.n,.....,1.n.n
而~
意味著有可能會有更高的修訂版本號。(也就是主版本、次版本不能變,修訂版本可以隨意變)。
相容某個次版本 如:~1.1.2,表示>=1.1.2 <1.2.0,可以是1.1.2,1.1.3,1.1.4,.....,1.1.n
看了上面版本號的指定後,我們可以知道,當我們使用了 ^
或者 ~
來控制依賴包版本號的時候 ,多人開發,就有可能存在大家安裝的依賴包版本不一樣的情況,就會存在專案執行的結果不一樣。
舉個例子
假設我們中安裝了 vue
, 當我們執行安裝 npm install vue -save
的時候,在專案中的package.json
的 vue
版本是 vue: ^3.0.0
, 我們電腦安裝的vue
版本就是 3.0.0
版本,我們把專案程式碼提交後,過了一段時間,vue 釋出了新版本 3.1.0
,這時新來一個同事,從新 git clone
克隆專案,執行 npm install
安裝的時候,在他電腦的vue版本就是 3.1.0
了,因為^只是鎖了主要版本,這樣我們電腦中的vue
版本就會不一樣。從理論上講(大家都遵循語意版本控制的話) ,它們應該仍然是相容的(因為次版本號的修改只是新功能,並不是不相容舊版本),這裡假設 vue
次版本的迭代會影響我們正在使用的功能,那麼這就會導致嚴重的問題,我們同一個專案會產生不同的執行結果。
這時也許有同學想到,那麼我們在package.json
上面鎖死依賴包的版本號不就可以了? 直接寫 vue: 3.0.0
鎖死,這樣大家安裝vue
的版本都是3.0.0
版本了。
這個想法固然是不錯的,但是你只能控制你自己的專案鎖死版本號,那你專案中依賴包的依賴包呢?你怎麼控制限制別人鎖死版本號呢?
description
欄位用來描述這個專案包,它是一個字串,可以讓其他開發者在 npm 的搜尋中發現我們的專案包。
author
顧名思義就是作者,表示該專案包的作者。
contributors
表示該專案包的貢獻者,和author
不同的是,該欄位是一個陣列,包含所有的貢獻者
homepage
就是專案的主頁地址了,它是一個字串。
repository
表示程式碼的存放倉庫地址
bugs
表示專案提交問題的地址
前面說到有開發依賴和生產依賴,其實npm還有同版本的依賴、捆綁依賴、可選依賴。
dependencies
生產依賴
devDependencies
開發依賴
peerDependencies
同版本的依賴
bundledDependencies
捆綁依賴
optionalDependencies
可選依賴
dependencies 表示專案依賴,這些依賴都會成為你的線上生產環境中的程式碼組成的部分。當它關聯到 npm 包被下載的時候,dependencies下的模組也會作為依賴,一起被下載。
devDependencies表示開發依賴, 不會被自動下載的。
因為 devDependencies 一般是用於開發階段起作用或是隻能用於開發環境中被用到的。 比如說我們用到的 Webpack
,前處理器 babel-loader
、scss-loader
,測試工具E2E
等, 這些都相當於是輔助的工具包, 無需在生產環境被使用到的。
這裡筆者囉嗦一句,當我們只開發應用,不對外開源的話,包隨意放在dependencies
或devDependencies
是不影響的,因為被用到的模組不管你再哪個依賴裡面都會被打包。但是如果開發的是庫檔案,是開源的,已經上傳到npm
倉庫的,這個你就得嚴格區分dependencies
和devDependencies
依賴了。因為當你在安裝第三方包的時候,只會同步下載第三方包dependencies
裡面的依賴,所以,當你第三方包的某依賴寫到devDependencies
中,被別人下載後沒下載到該依賴是會報錯執行不了的。
peerDependencies 表示同版本的依賴,很多小夥伴肯定難以理解,下面筆者舉個例子就明白了。
vuex
我們都使用過,vue
的狀態管理器,它肯定是依賴vue
的,但是我們檢視它的package.json
檔案,會發現dependencies
並沒有依賴vue
。
啊!這是怎麼回事呢?其實他就是用到了peerDependencies 同版本的依賴
。
這下知道什麼意思了吧,就是這個包它非常清楚的知道,你使用我的時候必定是在vue
環境下使用,所以你一定會安裝vue
,所以我就沒必要再在dependencies
下申明vue
依賴了,只需要在peerDependencies
申明依賴就行了,和主專案共用同一個vue
依賴,避免了重複安裝。
這樣的好處就是node_modules
裡面不會安裝兩個vue
。減少了node_modules
體積的同時大大提高了安裝速度。
bundledDependencies
和前面的依賴不同它是一個陣列,裡面定義了捆綁依賴。
"name": "test", "version": "1.0.0", "bundledDependencies": [ "bundleD1", "bundleD2" ]
當我們此時執行 npm pack
的時候, 就會生成一個 test-1.0.0.tgz
的壓縮包, 在該壓縮包中還包含了 bundleD1
和 bundleD2
兩個安裝包。
實際使用到這個壓縮包的時候,npm install test-1.0.0.tgz
的命令時, bundleD1
和 bundleD2
也會被安裝的。
這樣做的意義是什麼呢?
如果bundleD1
和bundleD2
包在npm
上有,能下載到固然沒意義。但是當bundleD1
和bundleD2
是自己臨時開發的,並且當前專案又依賴這兩個包,並且這兩個包在npm
上沒有,下載不到,這下就有意義了。相當於跟主包一起捆綁釋出。
這裡需要注意的是: 在 bundledDependencies 中指定的依賴包, 必須先在dependencies 和 devDependencies 宣告過, 否則 npm pack 階段是會報錯的。
optionalDependencies
表示可選依賴,就是說當你安裝對應的依賴項安裝失敗了, 也不會對整個安裝過程有影響的。一般我們很少會用到它, 這裡我是不建議大家去使用, 可能會增加專案的不確定性和複雜性。 瞭解即可。
當我們維護一些舊專案時,可能對npm
包的版本或者Node
版本有特殊要求,如果不滿足條件就可能無法將專案跑起來。為了讓專案開箱即用,可以在engines
欄位中說明具體的版本號:
"engines": { "node": ">=8.10.3 <12.13.0", "npm": ">=6.9.0" }
需要注意,engines
只是起一個說明的作用,即使使用者安裝的版本不符合要求,也不影響依賴包的安裝。
關於scripts
可以看看筆者前面寫的 npm script的那些騷操作,感興趣的小夥伴可以自行檢視。
config
欄位用來設定scripts
執行時的設定引數。
main
欄位用來指定載入的入口檔案,在 browser
和 Node
環境中都可以使用。如果我們將專案發布為npm
包,那麼當使用 require
匯入npm
包時,返回的就是main
欄位所列出的檔案的module.exports
屬性。如果不指定該欄位,預設是專案根目錄下的index.js
。如果沒找到,就會報錯。
browser
欄位可以定義 npm
包在 browser
環境下的入口檔案。如果 npm
包只在 web
端使用,並且嚴禁在 server
端使用,使用 browser
來定義入口檔案。
module
欄位可以定義 npm
包的 ESM
規範的入口檔案,browser
環境和 node
環境均可使用。如果 npm
包匯出的是 ESM
規範的包,使用 module
來定義入口檔案。
需要注意,*.js
檔案是使用 commonJS
規範的語法(require('xxx')),* .mjs
是用 ESM
規範的語法(import 'xxx')。
上面三個的入口入口檔案相關的設定是有差別的,特別是在不同的使用場景下。在Web
環境中,如果使用loader
載入ESM(ES module)
,那麼這三個設定的載入順序是browser→module→main
,如果使用require
載入CommonJS
模組,則載入的順序為main→module→browser
。
Webpack
在進行專案構建時,有一個target
選項,預設為Web
,即構建Web
應用。如果需要編譯一些同構專案,如node
專案,則只需將webpack.config.js
的target
選項設定為node
進行構建即可。如果在Node
環境中載入CommonJS
模組,或者ESM
,則只有main
欄位有效。
bin
欄位用來指定各個內部命令對應的可執行檔案的位置
"bin": { "someTool": "./bin/someTool.js" }, "scripts": { "dev": "someTool build" }
上面的例子相當於定義了一個命令someTool
,它對應的可執行檔案的位置是./bin/someTool.js
,這樣我們就能在scripts
裡面直接使用該命令了someTool
。
files
設定是一個陣列,用來描述當把npm
包作為依賴包安裝時需要說明的檔案列表。當npm
包釋出時,files
指定的檔案會被推播到npm
伺服器中,如果指定的是資料夾,那麼該資料夾下面所有的檔案都會被提交。
如果有不想提交的檔案,可以在專案根目錄中新建一個.npmignore
檔案,並在其中說明不需要提交的檔案,防止垃圾檔案推播到npm
上。這個檔案的形式和.gitignore
類似。寫在這個檔案中的檔案即便被寫在files
屬性裡也會被排除在外。比如可以在該檔案中這樣寫:
node_modules .vscode build .DS_Store
man
命令是 Linux
中的幫助指令,通過該指令可以檢視 Linux
中的指令幫助、組態檔幫助和程式設計幫助等資訊。如果 node.js
模組是一個全域性的命令列工具,在 package.json
通過 man
屬性可以指定 man
命令查詢的檔案地址。
man
欄位可以指定一個或多個檔案, 當執行man
{包名}時, 會展現給使用者檔案內容。
需要注意:
man
檔案必須以數位結尾,如果經過壓縮,還可以使用.gz
字尾。這個數位表示檔案安裝到哪個 man
節中;man
檔名稱不是以模組名稱開頭的,安裝的時候會加上模組名稱字首。對於上面的設定,可以使用以下命令來執行檢視檔案:
man npm-access man npm-audit
directories
欄位用來規範專案的目錄。node.js
模組是基於 CommonJS
模組化規範實現的,需要嚴格遵循 CommonJS
規範。模組目錄下除了必須包含包專案描述檔案 package.json
以外,還需要包含以下目錄:
在實際的專案目錄中,我們可能沒有按照這個規範進行命名,那麼就可以在directories
欄位指定每個目錄對應的檔案路徑:
"directories": { "bin": "./bin", "lib": "./lib", "doc": "./doc", "test" "./test", "man": "./man" },
這個屬性實際上沒有什麼實際的作用,當然不排除未來會有什麼比較有意義的用處。
private
欄位可以防止我們意外地將私有庫釋出到npm
伺服器。只需要將該欄位設定為true
。
preferGlobal
欄位表示使用者不把該模組安裝為全域性模組。如果設定為true
並把該模組安裝為全域性模組就會顯示警告。
它並不會真正的防止使用者進行區域性的安裝,只是對使用者進行提示,防止產生誤解。
publishConfig
設定會在模組釋出時生效,用於設定釋出時一些設定項的集合。如果不想模組被預設標記為最新,或者不想釋出到公共倉庫,可以在這裡設定tag或倉庫地址。
os
欄位可以讓我們設定該npm
包可以在什麼作業系統使用,不能再什麼作業系統使用。如果我們希望開發的npm包只執行在linux
,為了避免出現不必要的異常,建議使用Windows
系統的使用者不要安裝它,這時就可以使用os
設定:
"os" ["linux"] // 適用的作業系統 "os" ["!win32"] // 禁用的作業系統
該設定和OS
設定類似,用CPU
可以更準確的限制使用者的安裝環境:
"cpu" ["x64", "AMD64"] // 適用的cpu "cpu" ["!arm", "!mips"] // 禁用的cpu
可以看到,黑名單和白名單的區別就是,黑名單在前面加了一個!
。
license
欄位用於指定軟體的開源協定,開源協定表述了其他人獲得程式碼後擁有的權利,可以對程式碼進行何種操作,何種操作又是被禁止的。常見的協定如下:
typings或者types
欄位用來指定TypeScript
的入口檔案
eslint
的設定可以寫在單獨的組態檔.eslintrc.json
中,也可以寫在package.json
檔案的eslintConfig
設定項中。
babel
的設定可以寫在單獨的組態檔babel.config.json
中,也可以寫在package.json
檔案的babel
設定項中。
使用該欄位可以讓 npm
上所有的檔案都開啟 cdn
服務,該CND
服務由unpkg
提供。
lint-staged
是一個在Git
暫存檔案上執行linters
的工具,設定後每次修改一個檔案即可給所有檔案執行一次lint
檢查,通常配合gitHooks
一起使用。
使用lint-staged
時,每次提交程式碼只會檢查當前改動的檔案。
gitHooks
用來定義一個勾點,在提交(commit)之前執行ESlint
檢查。在執行lint
命令後,會自動修復暫存區的檔案。修復之後的檔案並不會儲存在暫存區,所以需要用git add
命令將修復後的檔案重新加入暫存區。在執行pre-commit
命令之後,如果沒有錯誤,就會執行git commit
命令
"gitHooks": { "pre-commit": "lint-staged" }
這裡就是配合lint-staged
來進行程式碼的檢查操作。每次commit
前執行lint-staged
。
browserslist
欄位用來告知支援哪些瀏覽器及版本。Babel、postcss、eslint
等工具都會用到它。
當然你也可以單獨建立.browserslistrc
檔案來設定。如需瞭解更多可以檢視browserslist 官方檔案。
前面說了package.json
裡面的包版本不是一個具體的版本,而是一個最優版本。而package-lock.json
裡面定義的是某個包的具體版本,以及包之間的層疊關係。
一個 package-lock.json 裡面的每個依賴主要是有以下的幾部分組成的:
dependencices
中的依賴項node_modeles
中依賴的包(特殊情況下才存在)。並不是所有的子依賴都有 dependencies
屬性,只有子依賴的依賴和當前已安裝在根目錄的 node_modules
中的依賴衝突之後, 才會有這個屬性。 這可能涉及巢狀情況的依賴管理。假設我們的專案依賴A、B、C
三個包,並且B
包又依賴特定版本的C
包,所以B
包就會有dependencices
,那麼我們專案的整個node_modules
的目錄結構如下
node_modules A.package B.package node_modules C.package C.package
當package.json
裡面不再使用最優版本,而是一個特定有效版本,也就是版本號前不帶修飾符,這樣package.json
和package-lock.json
裡面的版本號才是一致的。
或者我們npm install [email protected]
帶上版本號,安裝特定版本的包package.json
和package-lock.json
裡面的版本號也是一致的。
或者我們package.json
裡面定義的包版本就是最新的,我們安裝的時候package.json
和package-lock.json
裡面的版本號也會是一致的。
package-lock.json
在npm install
的時候會自動生成。
當我們修改依賴位置,比如將部分包的位置從 dependencies
移動到 devDependencies
這種操作,雖然包未變,但是也會影響 package-lock.json
,會將部分包的 dev
欄位設定為 true
。
還有如果我們安裝源 registry
不同,執行 npm install
時也會修改 package-lock.json
。
因為他是會記錄我們的依賴包地址的。
當我們使用npm install
新增或npm uninstall
移除包的時候,同時也會修改 package-lock.json
。
當我們更新某個包的版本的時候,同時也會修改 package-lock.json
。
我們知道,使用npm install xxx
會安裝某最新版本的包。
如果在根目錄下直接執行npm install
,那麼npm
會根據package.json
下載所有的最新版本的包。
那麼怎麼安裝指定版本的包呢?
我們只需要安裝的時候帶上版本號就可以啦。比如筆者上面element-ui
預設安裝的最新版本是2.15.9
。我們來安裝一個2.15.7
的特定版本。
npm install [email protected]
我們最新版本的2.15.9
的版本包就會被替換。並且它會同步修改我們的package.json
和package-lock.json
。
我們知道,安裝完生成package-lock.json
之後包的版本就會被固定下來,後續不管你怎麼npm install
都不會再變化。
如果我想更新到最新版本的包該怎麼辦呢?
更新包的版本有很多種方式。
我們知道最新包的版本,直接按上面的安裝指定包並帶上版本號即可。原理和安裝特定版本的包一致。
npm install [email protected]
它會同步修改我們的package.json
和package-lock.json
。
不知道最新包的版本,我們執行npm update xxx
即可。
npm update element-ui
它會將指定包更新成最新版本,並且同步修改我們的package.json
和package-lock.json
。
如果想更新專案下所有的包,直接執行 npm update
即可。
請注意,更新包它是會遵循我們的最優版本號控制的。也就是說當我們的版本是被^
修飾時,再怎麼更新它只會更新次版本和修訂版本,並不會更新主版本。
比如筆者安裝的element-ui
包的版本是1.0.0
package.json
裡面版本號如下
當我們npm update element-ui
更新包時,它只會更新成最新的次版本和修訂版本,並不會更新主版本。
package.json
裡面版本號如下
package-lock.json
如果想更新專案下所有的包我們還可以將package-lock.json
刪除,然後執行npm install
,它也會安裝所有的最新版本的包,並且會重新生成package-lock.json
。
至於我們要不要提交 lockfiles 到倉庫中?這個就需要看我們具體的專案的定位了。
如果是開發一個應用, 我的理解是 package-lock.json
檔案提交到程式碼版本倉庫.這樣可以保證專案中成員、運維部署成員或者是 CI 系統, 在執行 npm install
後, 保證在不同的節點能得到完全一致的依賴安裝的內容,減少bug
的出現。
如果你的目標是開發一個給外部環境用的庫,那麼就需要認真考慮一下了, 因為庫檔案一般都是被其他專案依賴的,在不使用 package-lock.json的情況下,就可以複用主專案已經載入過的包,減少依賴重複和體積
如果說我們開發的庫依賴了一個精確版本號的模組,那麼在我們去提交 lockfiles
到倉庫中可能就會出現, 同一個依賴被不同版本都被下載的情況,這樣加大了node_modules
的體積。如果我們作為一個庫的開發者, 其實如果真的使用到某個特定的版本依賴的需求, 那麼定義peerDependencies 是一個更好的選擇。
所以, 我個人比較推薦的一個做法是:把 package-lock.json
一起提交到倉庫中去, 不需要 ignore
。但是在執行 npm publish
命令的時候,也就是釋出一個庫的時候, 它其實應該是被忽略的不應該被髮布出去的。
在專案中如果沒有鎖版本的必要,可以不使用package-lock.json
,在安裝模組時指定--no-lock
即可。
我們都知道package-lock.json
主要是用來鎖定包版本的。
其實在npm
的發展歷史中,控制包的版本有package-lock.json
和npm-shrinkwrap.json
兩種方式
在npm5
之前(不包括5),主要是用npm-shrinkwrap.json
來精準控制安裝指定版本的npm
包。
那怎麼生成npm-shrinkwrap.json
呢?其實一條命令npm shrinkwrap
就能搞定。
它會生成一個npm-shrinkwrap.json
檔案,記錄目前所有依賴包(及更底層依賴包)的版本資訊。這樣當以後其他人執行npm install
命令時,npm
首先會找到npm-shrinkwrap.json
檔案,依照其中的資訊準確的安裝每一個依賴包,只有當這個檔案不存在時,npm
才會使用package.json
。
因為這是npm5
之前的方案,所以現在基本上看不到了。現在都是package-lock.json
方案。
相較npm-shrinkwrap.json
,package-lock.json
的優點是能自動生成。
官方檔案是這樣解釋的:package-lock.json
它會在 npm 更改 node_modules 目錄樹或者 package.json 時自動生成的 ,它準確的描述了當前專案npm
包的依賴樹,並且在隨後的安裝中會根據 package-lock.json
來安裝,保證是相同的一個依賴樹,不考慮這個過程中是否有某個依賴有小版本的更新。
當我們在一個專案中npm install
時候,會自動生成一個package-lock.json
檔案,和package.json
在同一級目錄下。package-lock.json
記錄了專案的一些資訊和所依賴的模組。這樣在每次安裝都會出現相同的結果,不管你在什麼機器上面或什麼時候安裝。
可以看到package-lock.json
裡面包的版本不再是最優版本啦,而是一個固定版本,這也是它為什麼鎖定版本的原因。
並且我們依賴的依賴它也會安裝一個特定的版本,並鎖定起來。比如element-ui
所依賴的throttle-debounce
所以當我們下次再npm install
時候,npm
發現如果專案中有 package-lock.json
檔案,則會根據 package-lock.json
裡的內容來處理和安裝依賴而不再根據 package.json
。
可見package-lock.json
原理就是將專案中用到的所有依賴都指定一個固定的版本,後續安裝直接讀取該檔案來安裝依賴。
在這裡需要注意,如果用的是cnpm
是不會自動生成package-lock.json
檔案的。我們平時開發最好的實踐就是使用npm
然後將映象設定為淘寶源就可以了。
// 設定淘寶映象 npm config set registry https://registry.npm.taobao.org // 檢視映象源 npm config get registry
當我們的專案第一次去搭建的時候, 使用 npm install
安裝依賴包, 並去提交 package.json、package-lock.json
, 至於node_moduled
目錄是不用提交的。
當我們作為專案的新成員的時候, checkout/clone
專案的時候, 執行一次 npm install
去安裝依賴包,它會根據package-lock.json
下載對應固定版本的包。
當我們出現了需要升級依賴的需求的時候:
升級小版本的時候, 依靠 npm update
升級大版本的時候, 依靠 npm install xxx
當然我們也有一種方法, 直接去修改 package.json 中的版本號, 並去執行 npm install 去升級版本
當我們本地升級新版本後確認沒有問題之後, 去提交新的 package.json 和 package-lock.json檔案。
當我們出現了需要降級依賴的需求的時候:
我們去執行npm install @x.x.x 命令後,驗證沒有問題之後, 是需要提交新的 package.json 和 package-lock.json 檔案。
當我們出現了需要刪除依賴的需求的時候:
當我們執行 npm uninstall 命令後,需要去驗證,提交新的 package.json
和 package-lock.json
檔案。
或者是更加暴力一點, 直接操作 package.json
, 刪除對應的依賴, 執行 npm install 命令, 需要去驗證,提交新的package.json 和 package-lock.json 檔案。
當你把更新後的package.json 和 package-lock.json提交到程式碼倉庫的時候, 需要通知你的團隊成員, 保證其他的團隊成員拉取程式碼之後,更新依賴可以有一個更友好的開發環境保障持續性的開發工作。
如果你的 package-lock.json 出現衝突或問題, 我的建議是將原生的 package-lock.json檔案刪掉, 然後去找遠端沒有衝突的 package.json 和 package-lock.json, 再去執行 npm install
命令。
好了,感謝小夥伴們的耐心觀看,關於詳解package.json和package-lock.json
今天就講到這裡。
更多node相關知識,請存取:!
以上就是一文解析package.json和package-lock.json的詳細內容,更多請關注TW511.COM其它相關文章!