全方位解讀 package-json
來自:知乎,作者:Derrick
鏈接:https://zhuanlan.zhihu.com/p/384484213
前言
平常在工作中,對package.json
這個文件的接觸非常非常少。
-
一些同學可能還會看一下 script 裏面有什麼命令,執行了哪些方法。
-
又或者瞭解一下
dependencies
和devDependencies
-
其他大部分的同學可能直接就
npm i
和npm start
就開始工作了。 -
但是
package.json
的魅力遠不止如此 -
今天就和我一起探索一下這個項目中不可或缺的——
package.json
吧!
由淺入深 - 核心內容
準備工作
手摸手新建一個空的 package.json
-
npm init
-
上萬個回車
或者直接執行
-
npm init -y
-
其意思就是全部都略過,和我們上面的無數個回車的效果一樣
先看看上面有的東西。
{
"name": "package.json", # 項目名稱
"version": "1.0.0", # 項目版本(格式:大版本.次要版本.小版本)
"description": "", # 項目描述
"main": "index.js", # 入口文件
"scripts": { # 指定運行腳本命令的 npm 命令行縮寫
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [], # 關鍵詞
"author": "", # 作者
"license": "ISC" # 許可證
}
scripts(快捷腳本)
scripts
字段是package.json
中的一種元數據功能,它接受一個對象,對象的屬性爲可以通過npm run
運行的腳本,值爲實際運行的命令(通常是終端命令),如:
"scripts": {
"start": "node index.js"
},
複製代碼
- 將終端命令放入
scripts
字段,既可以記錄它們又可以實現輕鬆重用。
dependencies & devDependencies(項目依賴)
-
dependencies
字段指定了項目運行所依賴的模塊 -
可以理解爲我們的項目在生產環境運行中要用到的東西。
-
比如說我們常用的
antd
只能哪個代碼塊就會用到裏面的組件,所以要放到dependencies
裏面去 -
devDependencies
字段指定了項目開發所需要的模塊 -
開發環境會用到的東西,比如說 webpack。我們打包的時候會用到,但是項目運行的時候卻用不到,所以只需要放到
devDependencies
中去就好了 -
類似的
eslint
之類的
這裏重點談一下這些版本號直接的差異
~1.1.1
-
~1.2.3
:=>=1.2.3 <1.(2+1).0
:=>=1.2.3 <1.3.0-0
-
~1.2
:=>=1.2.0 <1.(2+1).0
:=>=1.2.0 <1.3.0-0
(同1.2.x
) -
~1
:=>=1.0.0 <(1+1).0.0
:=>=1.0.0 <2.0.0-0
(同1.x
) -
~0.2.3
:=>=0.2.3 <0.(2+1).0
:=>=0.2.3 <0.3.0-0
-
~0.2
:=>=0.2.0 <0.(2+1).0
:=>=0.2.0 <0.3.0-0
(同0.2.x
) -
~0
:=>=0.0.0 <(0+1).0.0
:=>=0.0.0 <1.0.0-0
(同0.x
) -
~1.2.3-beta.2
:=>=1.2.3-beta.2 <1.3.0-0
請注意,1.2.3
版本中的預發佈將被允許,如果它們大於或等於beta.2
. 所以,1.2.3-beta.4
會被允許,但1.2.4-beta.2
不會,因爲它是不同[major, minor, patch]
元組的預發佈。
^1.1.1
允許不修改[major, minor, patch]
元組中最左邊的非零元素的更改 。換句話說,這允許版本1.0.0
及以上版本的補丁和次要更新,版本的補丁更新0.X >=0.1.0
,以及版本的_不_更新0.0.X
。
許多作者將0.x
版本視爲x
主要的 “重大變化” 指標。
當作者可能在發行版0.2.4
和0.3.0
發行版之間進行重大更改時,插入符範圍是理想的,這是一種常見做法。但是,它假定和之間_不會_有重大變化 。根據通常觀察到的做法,它允許進行假定爲附加(但不會破壞)的更改。0.2.4``0.2.5
-
^1.2.3
:=>=1.2.3 <2.0.0-0
-
^0.2.3
:=>=0.2.3 <0.3.0-0
-
^0.0.3
:=>=0.0.3 <0.0.4-0
-
^1.2.3-beta.2
:=>=1.2.3-beta.2 <2.0.0-0
請注意,1.2.3
版本中的預發佈將被允許,如果它們大於或等於beta.2
. 所以,1.2.3-beta.4
會被允許,但1.2.4-beta.2
不會,因爲它是不同[major, minor, patch]
元組的預發佈。 -
^0.0.3-beta
:=>=0.0.3-beta <0.0.4-0
請注意,_僅_允許0.0.3
版本中的預發佈 ,如果它們大於或等於. 所以,會被允許。beta``0.0.3-pr.2
解析插入符範圍時,缺失patch
值會被減爲數字0
,但即使主要版本和次要版本都是0
.
-
^1.2.x
:=>=1.2.0 <2.0.0-0
-
^0.0.x
:=>=0.0.0 <0.1.0-0
-
^0.0
:=>=0.0.0 <0.1.0-0
缺失值minor
和patch
值將脫糖爲零,但也允許在這些值內具有靈活性,即使主要版本爲零。
-
^1.x
:=>=1.0.0 <2.0.0-0
-
^0.x
:=>=0.0.0 <1.0.0-0
1.1.x
任何的X
,x
或*
可被用來 “立場在” 在數字值中的一個[major, minor, patch]
元組。
-
*
:=>=0.0.0
(任何版本都滿足) -
1.x
:=>=1.0.0 <2.0.0-0
(匹配主要版本) -
1.2.x
:=>=1.2.0 <1.3.0-0
(匹配主要和次要版本)
部分版本範圍被視爲 X 範圍,因此特殊字符實際上是可選的。
-
""
(空字符串):=*
:=>=0.0.0
-
1
:=1.x.x
:=>=1.0.0 <2.0.0-0
-
1.2
:=1.2.x
:=>=1.2.0 <1.3.0-0
1.1.1 - 1.1.2
指定一個包含集。
1.2.3 - 2.3.4
:=>=1.2.3 <=2.3.4
如果部分版本作爲包含範圍中的第一個版本提供,則缺失的部分將替換爲零。
1.2 - 2.3.4
:=>=1.2.0 <=2.3.4
如果部分版本作爲包含範圍中的第二個版本提供,則接受以元組提供的部分開頭的所有版本,但不會大於提供的元組部分。
-
1.2.3 - 2.3
:=>=1.2.3 <2.4.0-0
-
1.2.3 - 2
:=>=1.2.3 <3.0.0-0
engines(指定項目 node 版本)
-
有時候,新拉一個項目的時候,由於和其他開發使用的
node
版本不同,導致會出現很多奇奇怪怪的問題(如某些依賴安裝報錯、依賴安裝完項目跑步起來等)。 -
爲了實現項目開箱即用的偉大理想,這時候可以使用
package.json
的engines
字段來指定項目 node 版本:
"engines": {
"node": ">= 8.16.0"
},
複製代碼
- 該字段也可以指定適用的
npm
版本:
"engines": {
"npm": ">= 6.9.0"
},
複製代碼
- 需要注意的是,engines 屬性僅起到一個說明的作用,當用戶版本不符合指定值時也不影響依賴的安裝。
os(模塊適用系統)
-
假如我們開發了一個模塊,只能跑在
darwin
系統下,我們需要保證windows
用戶不會安裝到該模塊,從而避免發生不必要的錯誤。 -
這時候,使用
os
屬性則可以幫助我們實現以上的需求,該屬性可以指定模塊適用系統的系統,或者指定不能安裝的系統黑名單(當在系統黑名單中的系統中安裝模塊則會報錯):
"os" : [ "darwin", "linux" ] # 適用系統
"os" : [ "!win32" ] # 黑名單
複製代碼
Tips:在
node
環境下可以使用process.platform
來判斷操作系統。
cpu(指定模塊適用 cpu 架構)
- 和上面的
os
字段類似,我們可以用cpu
字段更精準的限制用戶安裝環境:
"cpu" : [ "x64", "ia32" ] # 適用 cpu
"cpu" : [ "!arm", "!mips" ] # 黑名單
複製代碼
Tips:在
node
環境下可以使用process.arch
來判斷cpu
架構。
private(定義私有模塊)
- 一般公司的非開源項目,都會設置
private
屬性的值爲true
,這是因爲npm
拒絕發佈私有模塊,通過設置該字段可以防止私有模塊被無意間發佈出去。
次重要(可以當百科全書)
name(項目名稱)
-
這個名稱和你要發佈項目到
npm
上的有關係。 -
假如你不想發佈的話那這個
name
和version
就不是必填項了
名字就是你的東西叫什麼。(name 名稱)和(version 版本號)構成一個唯一的標識符。
名稱的一些規則:
-
名稱必須小於或等於 214 個字符。這包括範圍包的範圍。
-
作用域包的名稱可以以點或下劃線開頭。這在沒有範圍的情況下是不允許的。
-
新包的名稱中不得包含大寫字母。
-
該名稱最終成爲 URL 的一部分、命令行上的參數和文件夾名稱。因此,名稱不能包含任何非 URL 安全字符。
一些技巧:
-
不要使用與核心節點模塊相同的名稱。
-
不要在名稱中加入 “js” 或“node”。假設它是 js,因爲您正在編寫 package.json 文件,並且您可以使用 “engines” 字段指定引擎。(見下文。)
-
該名稱可能會作爲參數傳遞給 require(),因此它應該是簡短的,但也應該具有合理的描述性。
-
您可能需要檢查 npm 註冊表以查看是否已經存在使用該名稱的內容,以免過於依賴它。https://www.npmjs.com/
-
方法一:直接到 npm 官網去搜
-
方法二:
npm view <packageName>
如果模塊存在,可以查看該模塊的一些基本信息:
如果該模塊名從未被使用過,則會拋出 404 錯誤:
version(版本號)
-
version
和name
組成在npm
內部的一個唯一標識符。 -
假如你不想發佈的話那這個
name
和version
就不是必填項了 -
版本必須可由 node-semver 解析 ,它作爲依賴項與 npm 捆綁在一起。(
npm install semver
自己使用。) -
我們可以執行以下命令查看模塊的版本:
npm view <packageName> version # 查看某個模塊的最新版本
npm view <packageName> versions # 查看某個模塊的所有歷史版本
npm view <packageName> version
description(項目描述)
此文檔是您需要了解的有關 package.json
文件中所需內容的全部信息。它必須是實際的 JSON
,而不僅僅是 JavaScript
對象文字。
本文檔中描述的許多行爲受 中描述的配置設置的影響config
。
keywords
把關鍵字放進去。它是一個字符串數組。這有助於人們發現您的包裹,因爲它在 中列出npm search
。
homepage(項目主頁)
項目主頁的url
。
例子:
"homepage" :“https://github.com/owner/project#readme”
bugs(問題追蹤)
項目問題跟蹤器的 url 和 / 或應報告問題的電子郵件地址。這些對於遇到包裹問題的人很有幫助。
它應該是這樣的:
{
"url" : "https://github.com/owner/project/issues" ,
"email" :"project@hostname.com"
}
您可以指定一個或兩個值。如果您只想提供一個 url,您可以將 “bugs” 的值指定爲一個簡單的字符串而不是一個對象。
如果提供了url
,它將被npm bugs
命令使用。
license(執照)
你應該爲你的包指定一個許可證,以便人們知道他們如何被允許使用它,以及你對它施加的任何限制。
如果您使用的是 BSD-2-Clause 或 MIT 等通用許可證,請爲您使用的許可證添加當前的SPDX
許可證標識符,如下所示:
{
"license" : "BSD-3-Clause"
}
您可以查看 SPDX 許可證 ID 的完整列表。理想情況下,您應該選擇 OSI 批准的一種。
如果您的軟件包在多個通用許可下獲得許可,請使用 SPDX 許可表達式語法版本 2.0 string,如下所示:
{
"license" : "(ISC OR GPL-3.0)"
}
如果您使用的許可證尚未分配SPDX
標識符,或者您使用的是自定義許可證,請使用如下字符串值:
{
"license" : "SEE LICENSE IN <filename>"
}
然後包含一個<filename>
在包的頂層命名的文件。
一些舊包使用許可證對象或包含許可證對象數組的 “許可證” 屬性:
// 無效的元數據
{
"license" : {
"type" : "ISC",
"url" : "https://opensource.org/licenses/ISC"
}
}
// 無效的元數據
{
"licenses" : [
{
"type": "MIT",
"url": "https://www.opensource.org/licenses/mit-license.php"
},
{
"type": "Apache-2.0",
"url": "https://opensource.org/licenses/apache2.0.php"
}
]
}
這些樣式現在已被棄用。相反,使用SPDX
表達式,如下所示:
{
"license": "ISC"
}
{
"license": "(MIT OR Apache-2.0)"
}
最後,如果您不希望根據任何條款授予他人使用私有或未發佈包的權利:
{
"license": "UNLICENSED"
}
還要考慮設置"private": true
以防止意外發布。
author, contributors(作者和貢獻者)
“作者”是一個人。“貢獻者”是一羣人。“person”是一個帶有 “name” 字段和可選的 “url” 和“email”的對象,像這樣:
{
"name" : "Barney Rubble",
"email" : "b@rubble.com",
"url" : "http://barnyrubble.tumblr.com/"
}
或者,您可以將其全部縮短爲一個字符串,然後 npm 將爲您解析它:
{
"author": "Barney Rubble <b@rubble.com> (http://barnyrubble.tumblr.com/)"
}
email 和 url 都是可選的。
npm 還使用您的 npm 用戶信息設置頂級 “維護者” 字段。
funding(檔案)
可選files
字段是一個文件模式數組,它描述了當您的包作爲依賴項安裝時要包含的條目。文件模式遵循與 類似的語法.gitignore
,但相反:包含文件、目錄或 glob 模式(*
,**/*
等)將使該文件在打包時包含在 tarball 中。省略該字段將使其默認爲["*"]
,這意味着它將包含所有文件。
一些特殊的文件和目錄也會被包含或排除,無論它們是否存在於files
數組中(見下文)。
您還可以.npmignore
在包的根目錄或子目錄中提供一個文件,以防止文件被包含在內。在包的根目錄中,它不會覆蓋 “文件” 字段,但在子目錄中會覆蓋。該.npmignore
文件就像一個.gitignore
. 如果有一個.gitignore
文件,並且.npmignore
丟失了,.gitignore
則將使用 的內容。
文件包含了 “的 package.json#文件” 欄中_無法_通過排除.npmignore
或.gitignore
。
無論設置如何,始終包含某些文件:
-
package.json
-
README
-
CHANGES
/CHANGELOG
/HISTORY
-
LICENSE
/LICENCE
-
NOTICE
-
“主要” 字段中的文件
README
, CHANGES
, LICENSE
&NOTICE
可以有任何大小寫和擴展名。
相反,一些文件總是被忽略:
-
.git
-
CVS
-
.svn
-
.hg
-
.lock-wscript
-
.wafpickle-N
-
.*.swp
-
.DS_Store
-
._*
-
npm-debug.log
-
.npmrc
-
node_modules
-
config.gypi
-
*.orig
-
package-lock.json
(npm-shrinkwrap.json
如果您希望發佈,請使用)
main(主要入口)
-
main
字段是package.json
中的另一種元數據功能,它可以用來指定加載的入口文件。假如你的項目是一個npm
包,當用戶安裝你的包後,require('my-module')
返回的是main
字段中所列出文件的module.exports
屬性。 -
當不指定
main
字段時,默認值是模塊根目錄下面的index.js
文件。
browser(瀏覽器)
如果您的模塊打算在客戶端使用,則應使用瀏覽器字段而不是主字段。這有助於提示用戶它可能依賴於 Node.js 模塊中不可用的原語。(例如 window
)
bin(自定義命令)
很多包都有一個或多個他們想要安裝到 PATH 中的可執行文件。npm 使這變得非常簡單(實際上,它使用此功能來安裝 “npm” 可執行文件。)
要使用它,請bin
在 package.json 中提供一個字段,它是命令名到本地文件名的映射。在安裝時,npm 會將該文件符號鏈接到prefix/bin
全局安裝或./node_modules/.bin/
本地安裝。
給大家看看我自己做一個簡單的 demo:
{
"name": "react-cli-library",
"version": "0.0.2",
"description": "",
"bin": {
"react-cli": "./bin/index.js"
},
}
我的名稱叫做 react-cli-library。
所以,npm i react-cli-library
安裝完成之後,執行 react-cli 就會有一些命令,他會執行我的根目錄底下./bin/index.js
這個文件。
雖然我的項目名稱是:react-cli-library
。但是我執行的內容卻是react-cli
,這個取決於 bin 的內容
man(快捷入口)
用來給 Linux 下的 man 命令查找文檔地址,是個單一文件或者文件數組。如果是單一文件,安裝完成後,他就是 man + 的結果,和此文件名無關,例如:
{
"name": "foo",
"version": "1.2.3",
"description": "A packaged foo fooer for fooing foos",
"main": "foo.js",
"man": "./man/doc.1"
}
通過 man foo 命令會得到 ./man/doc.1 文件的內容。如果 man 文件名稱不是以模塊名稱開頭的,安裝的時候會給加上模塊名稱前綴。因此,下面這段配置:
{
"name": "foo",
"version": "1.2.3",
"description": "A packaged foo fooer for fooing foos",
"main": "foo.js",
"man": [
"./man/foo.1",
"./man/bar.1"
]
}
會創建一些文件來作爲 man foo 和 man foo-bar 命令的結果。man 文件必須以數字結尾,或者如果被壓縮了,以. gz 結尾。數字表示文件將被安裝到 man 的哪個部分。
{
"name": "foo",
"version": "1.2.3",
"description": "A packaged foo fooer for fooing foos",
"main": "foo.js",
"man": [
"./man/foo.1",
"./man/foo.2"
]
}
會創建 man foo 和 man 2 foo 兩條命令。
directories(目錄)
CommonJS Packages 規範詳細說明了一些可以使用directories
對象指示包結構的方法。如果您查看 npm 的 package.json,您會看到它包含 doc、lib 和 man 目錄。
將來,這些信息可能會以其他創造性的方式使用。
目錄. bin
如果在 中指定bin
目錄directories.bin
,則將添加該文件夾中的所有文件。
由於bin
指令的工作方式,同時指定bin
路徑和設置directories.bin
是錯誤的。如果要指定單個文件,請使用bin
,對於現有bin
目錄中的所有文件,請使用directories.bin
。
目錄. man
一個充滿手冊頁的文件夾。Sugar 通過遍歷文件夾來生成 “man” 數組。
repository(代碼存儲位置)
指定代碼所在的位置。這對想要貢獻的人很有幫助。如果 git repo 在 GitHub 上,那麼該npm docs
命令將能夠找到您。
像這樣做:
{
"repository": {
"type": "git",
"url": "https://github.com/npm/cli.git"
}
}
URL 應該是一個公開可用的(可能是隻讀的)url,可以直接傳遞給 VCS 程序,無需任何修改。它不應該是您放入瀏覽器的 html 項目頁面的 url。是給電腦用的。
對於 GitHub、GitHub gist、Bitbucket 或 GitLab 存儲庫,您可以使用與 相同的快捷語法npm install
:
{
"repository": "npm/npm",
"repository": "github:user/repo",
"repository": "gist:11081aaa281",
"repository": "bitbucket:user/repo",
"repository": "gitlab:user/repo"
}
如果package.json
您的包的 不在根目錄中(例如,如果它是 monorepo 的一部分),您可以指定它所在的目錄:
{
"repository": {
"type": "git",
"url": "https://github.com/facebook/react.git",
"directory": "packages/react-dom"
}
}
config(配置內容)
“config” 對象可用於設置在升級過程中持續存在的包腳本中使用的配置參數。例如,如果一個包具有以下內容:
{
"name": "foo",
"config": {
"port": "8080"
}
}
然後有一個 “開始” 命令,然後引用 npm_package_config_port
環境變量,然後用戶可以通過執行npm config set foo:port 8001
.
查看config
和scripts
瞭解更多關於包配置的信息。
peerDependencies(對等依賴)
在某些情況下,您希望表達您的包與主機工具或庫的兼容性,而不必執行require
此主機的操作。這通常稱爲_插件_。值得注意的是,您的模塊可能會公開主機文檔所預期和指定的特定接口。
例如:
{
"name": "tea-latte",
"version": "1.3.5",
"peerDependencies": {
"tea": "2.x"
}
}
這確保您的軟件包tea-latte
只能與主機軟件包的第二個主要版本_一起_安裝tea
。npm install tea-latte
可能會產生以下依賴圖:
├── tea-latte@1.3.5
└── tea@2.2.0
在 npm 版本 3 到 6 中,peerDependencies
不會自動安裝,如果在樹中發現對等依賴項的無效版本,則會發出警告。由於 NPM V7 的,peerDependencies 被 默認安裝。
如果無法正確解析樹,嘗試安裝具有衝突要求的另一個插件可能會導致錯誤。因此,請確保您的插件要求儘可能廣泛,而不是將其鎖定爲特定的補丁版本。
假設主機符合 semver,只有主機包的主要版本中的更改纔會破壞您的插件。因此,如果您使用過主機包的每個 1.x 版本,請使用"^1.0"
或"1.x"
來表達這一點。如果您依賴 1.5.2 中引入的功能,請使用 "^1.5.2"
.
peerDependenciesMeta(捆綁依賴)
這定義了在發佈包時將捆綁的包名稱數組。
如果您需要在本地保留 npm 包或通過單個文件下載使它們可用,您可以通過在bundledDependencies
數組中指定包名稱並執行npm pack
.
例如:
如果我們像這樣定義 package.json:
{
"name": "awesome-web-framework",
"version": "1.0.0",
"bundledDependencies": [
"renderized",
"super-streams"
]
}
我們可以awesome-web-framework-1.0.0.tgz
通過運行獲取文件npm pack
。此文件包含的依賴關係renderized
,並super-streams
可以通過執行安裝在一個新的項目npm install awesome-web-framework-1.0.0.tgz
。請注意,包名稱不包含任何版本,因爲該信息在dependencies
.
如果這是拼寫"bundleDependencies"
,那麼這也很榮幸。
optionalDependencies(可選依賴項)
如果可以使用依賴項,但如果找不到或安裝失敗,您希望 npm 繼續,那麼您可以將其放入 optionalDependencies
對象中。這是包名稱到版本或 url 的映射,就像dependencies
對象一樣。不同之處在於構建失敗不會導致安裝失敗。運行npm install --no-optional
將阻止安裝這些依賴項。
處理缺少依賴項仍然是您的程序的責任。例如,這樣的事情:
try {
var foo = require('foo')
var fooVersion = require('foo/package.json').version
} catch (er) {
foo = null
}
if ( notGoodFooVersion(fooVersion) ) {
foo = null
}
// .. then later in your program ..
if (foo) {
foo.doFooThings()
}
中的條目optionalDependencies
將覆蓋 中的同名條目 dependencies
,因此通常最好只放在一個地方。
publishConfig(發佈配置)
這是一組將在發佈時使用的配置值。如果您想設置標記、註冊表或訪問權限,這將特別方便,這樣您就可以確保給定的包沒有被標記爲 “最新”、未發佈到全局公共註冊表或默認情況下範圍模塊是私有的。
查看config
可覆蓋的配置選項列表。
workspaces(工作區)
可選workspaces
字段是一個文件模式數組,它描述了本地文件系統內的位置,安裝客戶端應該查找這些位置以找到需要符號鏈接到頂級文件夾的每個工作區node_modules
。
它可以描述要用作工作區的文件夾的直接路徑,也可以定義將解析爲這些相同文件夾的 glob。
在以下示例中,./packages
只要文件夾中包含有效package.json
文件,位於文件夾內的所有文件夾 都將被視爲工作區 :
{
"name": "workspace-example",
"workspaces": [
"./packages/*"
]
}
有關workspaces
更多示例,請參見。
總結
本文幾乎是全網最全的 package.json 的講解了。一些常用的和不常用的都有區分,不常用的可以當百科全書查一下,面試主要也是會問一些主要內容。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/W1MxoZKCnCumWWbOIWVizw