Angular7 Npm Package.Json文件詳解
近期時間比較充裕,正好想了解下Angular Project相關內容。於是將Npm官網上關於Package.json的官方說明文檔進行了一下翻譯學習,僅供參考
原文出處: https://docs.npmjs.com/files/package.json
官方傳送門
npm-package.json 特性說明
描述
本文介紹了package.json文件中,你需要了解的所有內容。Package.json文件必須是一個真正的Json格式文件,而不能是一個通俗上理解的JavaScript對象。
本文中講到的很多操作指令來源於npm-config中的配置節點。
name
如果你想要發布npm包,最重要的是包中package.json文件中必須包含的name和version屬性。name和verion組合在一起,標識了這個包的唯一性。包中任何的改變都應該同步進行版本(version)的變更,如果你不想把你的包發布到公共環境中去,name和version屬性就變成了可選項。
name就是這個包被叫做的名字。命名需要按照這些規范:
- name必須少於等於214個字符,這214個字符包含了這個包的域名的全部字符。
- name不能以點(".") 和下划線("_")開頭
- 新包的名稱中不能包含大寫字母
- 包的名稱最終會成為URL的一部分、一個命令行的參數或者一個文件夾得名稱,因此,name不能包含任何非URL安全的字符。
小建議
- 對於核心的node模塊不要使用相同的名字
- 名字中不要包含“js”或者“node”字符。以js舉例,假設你正在寫一個package.json文件,你用“engines”描述“引擎”屬性.(詳細請往下看)
- 名稱有可能會被當做一個參數傳遞給require(),所以他應該盡量短,並且能夠合理的描述。
- 在你確定好名字之前。你可以通過npm reqistry看一下是否已經存在相同名稱的包,https://www.npmjs.com/
名稱可能會包含一個前綴,比如@myorg/mypackage,更多scope信息可以查看npm-scope 章節
version
如果想要發布npm包,最重要的是包中package.json文件中必須包含的name和version屬性。name和verion組合在一起,標識了這個包的唯一性。包中任何的改變都應該同步進行版本(version)的變更,如果你不想把你的包發布到公共環境中去,name和version屬性就變成了可選項。
Version必須能夠被node-semver解析,node-semvery作為一個以來依附於npm(可以通過 npm install semver安裝使用)
版本數值和范圍相關的更多內容可以查看semver
description
package.json中包含description屬性,他是一個字符串類型,由於npm的搜索會查找這個屬性,所以,這個屬性能夠讓其他人更好的找到您發布的包。
keywords
package.json中包含keywords屬性。他是一個字符串數組,由於npm的搜索會查找這個屬性,所以,這個屬性能夠讓其他人更好的找到您發布的包。
homepage
這個url地址能夠鏈接項目的主頁上,例如:
"homepage": "https://github.com/owner/project#readme"
bugs
這個url地址用於提交問題,他也可以是一個郵箱地址。對在使用你的包的過程中遇到bug的任非常有用。看起來應該是這樣的:
{ "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 license 查看SPDX授權的id列表,當然,你應該選擇接近OSI標准的授權。
如果你的包擁有多個通用的授權,可以使用一個SPDX 2.0版本的授權表達式,就像這樣:
{ "license" : "(ISC OR GPL-3.0)" }
如果你正在使用一個沒有被SPDX認證過的授權,或者你正在使用一個專用的授權碼,可以將信息配置成如下的值:
{ "license" : "SEE LICENSE IN <filename>" }
然后在包的最頂端添加一個名稱為
一些舊的包使用授權許可對象或者一個包含授權對象數組的“licenses”屬性。
// Not valid metadata
{ "license" :
{ "type" : "ISC"
, "url" : "https://opensource.org/licenses/ISC"
}
}
// Not valid metadata
{ "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來防止意外發布出去。
people fields:author,contributors
author是一個人,contributors是一個包含多個人的數組。persion是一個包含名稱屬性,並且url和email可選的得對象。如下所示:
{ "name" : "Barney Rubble"
, "email" : "b@rubble.com"
, "url" : "http://barnyrubble.tumblr.com/"
}
或者你也可以把內容簡寫到一個字符串中,npm可以將它解析出來:
"Barney Rubble <b@rubble.com> (http://barnyrubble.tumblr.com/)"
email和url都是可選的。
npm也可以設置一個頂級的"maintainers"屬性到用戶信息中。
files
files屬性是一個文件模板的數組,他描述了包被當做依賴安裝時所要包含的文件。文件模板語法類似.gitignore,但是與git相反,它表示包含了文件、目錄、或者全局屬性( *、**/*等),打包完成后,文件會被放到tarball中,省略該屬性將會按照默認值["*"]來處理,默認處理會包含所有的文件。
一些特殊的文件和目錄也可以被包含或者排除,無論他們是否在files數組中(繼續往下看)
你也可以提供一個.npmignore 文件在包的根目錄上或者子目錄上。以防止文件被包含到里面。在你文件的根目錄上他將會重寫files屬性。但是子目錄上.npmignore文件工作起來像是gitignore。如果有一個gitignore文件並且npmignore丟失了,gitignore的內容將會起作用。
包含"package.json#files"屬性的文件不能通過npmignore或者gitignore排除。
以下文件經常被包含,忽略配置的話:
- packge.json
- README
- CHANGES / CHANGELOG / HISTORY
- LICENSE / LICENCE
- NOTICE
- the file in the main field
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(可以用shrinkwrap替代)
main
main屬性是一個模塊id,也是程序的唯一入口。換句話說,如果你的包名叫foo,用戶安裝了他,然后用戶就可以通過使用require(
"foo")將main模塊中export的內容導入進去。
這個模塊id應該是與包所在的文件夾根目錄的相對路徑。
對大部分模塊來將,添加一個main腳本是有意義的,通常他並不會包含太多內容。
browser
如果模塊是在客戶端使用,你應該使用browser字段而不是main字段。這對暗示用戶,模塊依賴的一些node.js中無法獲取的,像window一樣的瀏覽器基礎對象,是非常有用的。
bin
許多的包至少有一個可執行文件需要被安裝到 Path目錄中。npm讓這變得非常簡單。(事實上,正是通過這個特性來安裝npm的可執行文件)
為了達到目標,package.json中提供了一個bin屬性,他在命令和本地文件名之間建立了一個映射。全局(global)安裝時,npm會將文件路徑寫入到prefix/bin下面,對於本地安裝,npm會建立./node_modules/.bin/ 和文件路徑的映射。
例如,myapp應當包含下面內容:
{ "bin" : { "myapp" : "./cli.js" } }
所以,當你安裝myapp時,這將會創建一個從cli.js腳本到/usr/local/bin/myapp.路徑的一個變量。
如果只有一個可執行文件,並且名字是包的名字,那么可以如下例子一樣只寫一個字符串。
{ "name": "my-program"
, "version": "1.2.5"
, "bin": "./path/to/program" }
或者和這類似
{ "name": "my-program"
, "version": "1.2.5"
, "bin" : { "my-program" : "./path/to/program" } }
請確保bin中的文件是以#!/usr/bin/env node開頭,不然,腳本腳本執行的時候會找不到node的可執行文件。
man
指定單一文件或者多個文件名來讓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文件了。
如果文件名不是以包名開頭的。那么他會被添加上前綴:
{ "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和man2 foo 兩個文件。
directories
CommonJs的包描述了你能夠通過directories查看到包結構的幾種方法。如果你查看他的package.json文件。你會看到里面有directiories標識的doc、lib、和man。
未來,這條信息可能會其他創造性的方法所用到。
directories.lib
他告訴別人你這些庫的位置,這個庫的文件夾並沒有其他的什么特殊用處,但是他是一個非常有用的元數據信息。
directories.bin
如果你指定了directories.bin中的一個bin文件夾。文件夾中的所有文件都會被添加進來。
由於bin指令的工作方式。他會指定一個bin路徑,同時會將配置的directiores.bin配置設置為無效,如果你想要指定個人的文件,可以使用bin,並且對於所有bin下面已經存在的文件,可以使用directories.bin。
directories.man
他是一個存放man頁的文件夾,通過移動文件夾可以生成一個man數組。
directories.doc
存放markdown文件,最終他會很好的顯示出來。
directories.exaple
存放demo腳本的地方,以后的某一天它可能會以一種巧妙的方式暴露出來。
directories.test
存放測試文件的地方,當前他並沒有暴露出來,但是未來可能會暴露出來。
repository
指定的存放代碼的地方,這對想要完善代碼得人是非常有用的,如果他是在github上的git倉庫,那么npm docs 命令可以找到他。
就像這樣:
"repository": {
"type" : "git",
"url" : "https://github.com/npm/cli.git"
}
"repository": {
"type" : "svn",
"url" : "https://v8.googlecode.com/svn/trunk/"
}
URL應該是個公開可訪問的地址,他能夠被VCS程序直接訪問,而不用做任何修改,他不應該是一個瀏覽區輸入的html頁面地址。他是給計算機用的。
對GitHub、GitHub gist、Bitbucket或者GitLab倉庫你可以使用相同的縮寫形式:
"repository": "npm/npm"
"repository": "github:user/repo"
"repository": "gist:11081aaa281"
"repository": "bitbucket:user/repo"
"repository": "gitlab:user/repo"
scripts
scripts 屬性是一個包含包運行時生命周期各個環節需要執行的腳本命令,key就是生命周期時間,value是運行時節點執行的命令。
可以查看npm-scripts查看更所script命令。
config
config對象用於在升級過程中配置包中腳本的配置參數。例如,如果一個包包含以下內容:
{ "name" : "foo"
, "config" : { "port" : "8080" } }
同時有一個start命令,引用了npm_package_config_port環境變量。name用戶可以通過npm config set foo:port 8001來重寫他。
可以查看npm-config和npm-script查看更多信息。
dependencies
Dependencies指定了一個報名和版本范圍的簡單對象。版本范圍是一個包含一個或多個分隔符的字符串。Dependencies也可以使用tar包或者git Url標記。
請不要在Dependencies中配置測試或者過度內容,devDependencies可以查看下面。
通過semver查看更多指定的版本范圍.
- version 必須完全匹配版本號
-
version 必須大於這個版本號
-
=version 必須大於等於
- <version
- <=version
- `version 與版本今夕向東 詳細查看semver
- ^version 與版本兼容 詳細查看semver
- 1.2.x 1.2.0,1.2.1等等,但不能是1.3.0
- http://... 詳細查看下面的'URL as Dependencies'
- * 可以與任何版本匹配
- "" (就像是空字符串)與*相同
- version1-version2 與 >=version1 <=version2相同
- range1 || range2 滿足range1或者range2中的任何一個都認為是通過,
- git... 查看下面的Git URLs as Dependencies
- user/repo 查看下面的GitHub URLs
- tag 一個特殊的版本,被當做標記進行標記或者發布。查看npm-dist-tag
- path/path/path 查看Local Paths
示例,以下所有都是可用的。
{ "dependencies" :
{ "foo" : "1.0.0 - 2.9999.9999"
, "bar" : ">=1.0.2 <2.1.2"
, "baz" : ">1.0.2 <=2.3.4"
, "boo" : "2.0.1"
, "qux" : "<1.0.0 || >=2.3.1 <2.4.5 || >=2.5.2 <3.0.0"
, "asd" : "http://asdf.com/asdf.tar.gz"
, "til" : "~1.2"
, "elf" : "~1.2.3"
, "two" : "2.x"
, "thr" : "3.3.x"
, "lat" : "latest"
, "dyl" : "file:../dyl"
}
}
URLs as Dependencies
你可以制定一個tarball url 代替一個版本的范圍
Git URLs as Dependencies
git url的格式如下
<protocol>://[<user>[:<password>]@]<hostname>[:<port>][:][/]<path>[#<commit-ish> | #semver:<semver>]
他可以用於准確的克隆一個commit,如果commit-ish按照如下格式:#semver:
,
可以是任何可用的semver范圍或者准確的版本,並且npm會查找遠程倉庫中任何匹配的標記或者引用。他們大部分都應該是注冊的依賴。指定#
或者#semver:
時,默認使用master分支。
示例:
git+ssh://git@github.com:npm/cli.git#v1.0.27
git+ssh://git@github.com:npm/cli#semver:^5.0
git+https://isaacs@github.com/npm/cli.git
git://github.com/npm/cli.git#v1.0.27
GitHub URLs
1.1.65版本之后,你可以像"foo":"user/foo-project"這樣引用GitHub Urls。使用git urls的時候需要添加commit-ish后綴,例如:
{
"name": "foo",
"version": "0.0.0",
"dependencies": {
"express": "expressjs/express",
"mocha": "mochajs/mocha#4727d357ea",
"module": "user/repo#feature\/branch"
}
}
Local Paths
2.0.0版本以后你可以給包含包的本地文件夾制定一個路徑。Local paths可以通過npm install -S或者npm install --save指令來保存。可以使用以下格式:
../foo/bar
~/foo/bar
./foo/bar
/foo/bar
他們會被轉換成一個相對地址並添加到package.json文件中。例如:
{
"name": "baz",
"dependencies": {
"bar": "file:../foo/bar"
}
}
這個特性對本地離線的開發和創建那些不需要訪問外部服務器進行npm安裝的測試文件是非常有用的。 #### DevDependencies
如果有人要下載並使用你發布的模塊。但是他們可能並不想或者並不需要下載編譯你使用的外部測試程序或者框架文檔。
這種情況下,最好將這些附加項放到devDependencies這個對象中。
這些包將會在根目錄下執行npm link或者npm install的時候安裝,並且可以像其他npm配置參數一樣管理使用,可以查看npm-config查看詳細信息。
對於編譯打包環節並沒有指定特定的平台,比如編譯CoffeeScript或者其他類似JavaScript的語言。可以使用prepare腳本來編譯,並且把他們依賴的包放到devdependency中。
示例:
{ "name": "ethopia-waza",
"description": "a delightfully fruity coffee varietal",
"version": "1.2.3",
"devDependencies": {
"coffee-script": "~1.6.3"
},
"scripts": {
"prepare": "coffee -o lib/ -c src/waza.coffee"
},
"main": "lib/waza.js"
}
preapare腳本會在publishing之前執行,所以,用戶可以不通過require就可以編譯他們,在開發模式下(比如本地執行的npm install),也會執行這個腳本,所以你可以很輕松的測試他。
peerDependencies
在某些場景下,你需要通過工具或者庫表示你的包的兼容性,但是並不想在通過require引用他,這通常指的是plugin,需要注意的是,你的模塊需要暴露一個特定的接口,規范,並在文檔中描述制定。
例如:
{
"name": "tea-latte",
"version": "1.3.5",
"peerDependencies": {
"tea": "2.x"
}
}
這可以確保包tea-latte與tea模塊的次版本(X)的包一起安裝.npm install tea-latte會按照如下依賴關系圖生成
├── tea-latte@1.3.5
└── tea@2.2.0
建議:npm1.0版本和2.0版本會自動安裝peerDependencies,他們不會依賴更高版本的依賴書,在npm 3.X版本中對此作了修改,當peerdependency沒有安裝的時候,你會收到一個警告提示。 1.x和2.X版本的操作經常混淆,並且很容易會版帶入依賴地獄(dependncy hell),現在npm需要盡可能的避免他。
安裝帶有沖突的以來的其他插件會報錯,所以,請確保你的插件依賴盡可能的全面,並且不要指定特定的版本號。
假如通過semver進行編譯,只改變package.json的主版本號會影響你的插件。因此,如果你有1.x的版本使用"^1.0"或者"1.x",如果你依賴1.5.2提供的特性,可以使用">=1.5.2 <2".
bundkedDependencies
他定義了一個發布包時會被捆綁發布的包名的數組,
如果需要在本地保留npm包或通過單個文件下載使其可用,通過在bundledDependencies數組中指定包名稱並執行npm pack,可以將包打包到tarball文件中。
例如:定義了如下的package.json
{
"name": "awesome-web-framework",
"version": "1.0.0",
"bundledDependencies": [
"renderized", "super-streams"
]
}
我們能夠通過npm pack獲取awesome-web-framework-1.0.0.tgz文件。這個文件包含了依賴renderized和super-streams兩個包,這兩個包可以在一個新工程中通過npm install awesome-web-framework-1.0.0.tgz.安裝
optionalDependencies§
如果可以使用依賴項,同時在找不到或者安裝失敗時希望繼續,那么你可以把它放到optionalDependencies配置對象中,他是一個程序包名稱和版本或者URL的字典,就像dependencies對象一樣,不同的是,編譯失敗后不會引起安裝失敗。
處理依賴的缺失仍然是程序的主要職責,就像這樣:
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中同名的文件,所以,對同一個文件最好只放到一個配置節下。
engines
你可以指定node的版本
{ "engines" : { "node" : ">=0.10.3 <0.12" } }
除非用戶已經設置了engine-strict配置標簽,否則,這個屬性只是一個建議值,並且它只會在你的包安裝依賴的時候產生警告信息。
engineStrict
這個特性在npm3.0版本中被刪除
OS
你可以指定你的模塊運行在那個操作系統中:
"os" : [ "darwin", "linux" ]
你也可以通過添加字符‘!’列出一個黑名單系統
"os" : [ "!win32" ]
主機的操作系統有process.plateform決定
這里可以使用黑名單,也可以使用白名單,盡管並沒有什么很好的原因解釋他。
cpu
如果你的代碼只能夠在特定的cpu架構下執行,你也可以指定他:
"cpu" : [ "x64", "ia32" ]
和操作系統一樣,你也可以使用黑名單
"cpu" : [ "!arm", "!mips" ]
主機的架構有process.arch決定。
preferGlobal
反方
這個選項用於觸發一個npm警告,但是他已經不再能發出警告,他現在只是單純的用於提示的信息,現在建議將二進制文件當做本地的開發依賴項(devDependencies)來處理。
private
如果package.json中設置了"private":true,那么npm將會拒絕發布他,這是一種防止意外發布的方法,如果你想將一個特定的包發送到一個特定的位置(例如:內部注冊國的位置),在發布時使用publishConfig 字典來重寫registry配置參數。
publishConfig
這是在發布時使用的一系列的配置值,當你想要設置tag,registry或者access的時候特別方便,以至於你可以確定一個包是否有"latst"標記,是否被默認發布到了公共的注冊地址。
任何配置值都可以被重寫,當然除了tag,registry和access,這可能是因為他們和發布的意圖有關。
查看更多細節npm-config.
DEFAULT VALUES
npm創建package是會默認帶上一些配置信息:
- "script":{"start":"node server.js"}
如果在package的根目錄有一個server.js文件。那么npm會默認添加指向node server.js的start命令 - "scripts":{"install":"node-gyp rebuild"}
如果根目錄下存在binding.gyp文件,並且沒有定義install或者preinstall 腳本,npm會默認添加intall命令來用node-gyp執行編譯。 - "contributors":[]
如果根目錄下有AUTHORS文件,npm
會將每行按照Name(url)格式來解析,email或者url是可選的。以#或者空格開頭的行將會被忽略。