Node 項目在項目根目錄中名為 package.json 的文件中跟蹤依賴關系和元數據剧罩。這是你項目的核心栓拜。它包含名稱、描述和版本之類的信息惠昔,以及運行幕与、開發(fā)以及有選擇地將項目發(fā)布到 NPM 所需的信息。
在本教程中镇防,我們將:
- 了解 package.json 與項目之間的關系
- 確定重要字段和元數據
- 了解如何管理 package.json
目標
了解什么是 package.json 文件啦鸣,它與你項目的關系以及需要了解的常見屬性。
了解 package.json
如果你以前用過 Node.js来氧,則可能會遇到 package.json 文件诫给。它是一個 JSON 文件,位于項目的根目錄中啦扬。你的 package.json 包含關于項目的重要信息中狂。它包含關于項目的使人類可讀元數據(如項目名稱和說明)以及功能元數據(如程序包版本號和程序所需的依賴項列表)。
package.json 示例如下所示:
{
"name": "my-project",
"version": "1.5.0",
"description": "Express server project using compression",
"main": "src/index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon",
"lint": "eslint **/*.js"
},
"dependencies": {
"express": "^4.16.4",
"compression": "~1.7.4"
},
"devDependencies": {
"eslint": "^5.16.0",
"nodemon": "^1.18.11"
},
"repository": {
"type": "git",
"url": "https://github.com/osiolabs/example.git"
},
"author": "Jon Church",
"contributors": [
{
"name": "Amber Matz",
"email": "example@example.com",
"url": "https://www.osiolabs.com/#team"
}
],
"keywords": [
"server",
"osiolabs",
"express",
"compression"
]
}
package.json 的用途是什么扑毡?
項目的 package.json 是配置和描述如何與程序交互和運行的中心胃榕。 npm CLI(和 yarn)用它來識別你的項目并了解如何處理項目的依賴關系。package.json 文件使 npm 可以啟動你的項目僚楞、運行腳本勤晚、安裝依賴項、發(fā)布到 NPM 注冊表以及許多其他有用的任務泉褐。 npm CLI 也是管理 package.json 的最佳方法赐写,因為它有助于在項目的整個生命周期內生成和更新 package.json 文件。
package.json 會在項目的生命周期中扮演多個角色膜赃,其中某些角色僅適用于發(fā)布到 NPM 的軟件包挺邀。即使你沒有把項目發(fā)布到 NPM 注冊表中,或者沒有將其公開發(fā)布給其他人,那么 package.json 對于開發(fā)流程仍然至關重要端铛。
你的項目還必須包含 package.json泣矛,然后才能從 NPM 安裝軟件包。這可能是你在項目中需要它的主要原因之一禾蚕。
package.json 中的常見字段
讓我們看一下 package.json 中包含的一些最常見和重要的字段您朽,以更好地了解如何使用和管理這個基本文件。有些用來發(fā)布到 NPM换淆,而其他一些則可以幫助 npm CLI 運行應用程序或安裝依賴項哗总。
實際的字段比我們所介紹的要多,你可以在它的文檔中了解其余字段倍试,但以下的是必須要了解的 package.json 屬性讯屈。
name
package.json 中最重要的屬性是 name
和 version
兩個屬性,這兩個屬性是必須要有的县习,否則模塊就無法被安裝涮母,這兩個屬性一起形成了一個 npm 模塊的唯一標識。
name是 package(包)的名稱躁愿。名稱的第一部分(如@scope/是可選的,用作名稱空間)叛本。當我們的包發(fā)布到 NPM 網站,其他人才能通過搜索name來安裝使用
{
"name": "@scope/name"
}
name 規(guī)范
- 最好取簡短而語義化的值
- 不能以,.開頭
- 不能有大寫字母/空格/下滑線!
- 不能和 NPM 網站中已有的包名字重名攘已!
version
version
是 package(包)的版本,通常炮赦,它不會對你的項目產生任何影響,
除非它是一個工作空間(workspaces)-其版本必須與指定的范圍相匹配样勃,才能選擇該工作空間作為解決方案的候選對象。
version 規(guī)范
version
具體體現為::“x.y.z”
- 修復 bug,小改動性芬,增加 z
- 增加了新特性峡眶,但仍能向后兼容,增加 y
- 有很大的改動植锉,無法向后兼容,增加 x
詳細內容參考語義化版本 2.0.0
使用 npm version <update_type>自動升級版本號
update_type為patch, minor, major其中之一辫樱,分別表示補丁
,小改
俊庇,大改
npm version patch
npm version minor
npm version major
在 CI(持續(xù)集成)的腳本中可以用到此命令
description
一個描述狮暑,方便別人了解你的模塊作用,搜索的時候也有用辉饱。
{
"description": "xxxx"
}
keywords
一個字符串數組搬男,方便別人搜索到本模塊
{
"keywords": [
"ant",
"component",
"design"
]
}
當我們使用 npm 檢索模塊時,會對模塊中的 description 字段和 keywords 字段進行匹配彭沼,寫好 package.json 中的 description 和 keywords 將有利于增加我們模塊的曝光率缔逛。
homepage
項目主頁 url,默認值為/
一般來說,我們打包的靜態(tài)資源會部署在 CDN 上,為了讓我們的應用知道去哪里加載資源褐奴,則需要我們設置一個根路徑按脚,這時可以通過 package.json 中的 homepage 字段設置應用的根路徑。
{
"homepage": "https://ant.design"
}
bugs
填寫一個 bug 提交地址或者一個郵箱敦冬,被你的模塊坑到的人可以通過這里吐槽辅搬,例如:
{
"bugs": {
"url":"https://github.com/ant-design/ant-design/issues"
}
}
license
你應該為你的開源代碼模塊制定一個開源協(xié)議,讓用戶知道他們有何權限來使用你的模塊脖旱,以及使用該模塊有哪些限制
- MIT 是最少約束的選擇堪遂。
- GPL 是最多約束的。
如果是個人隨意作品夯缺,建議 MIT 許可蚤氏。如果是公司或者需要嚴格保護的開源產品,GPL踊兜。
{
"license": "MIT"
}
詳細內容參考
和用戶相關的屬性: author, contributors
{
"author": "iikonan",
"contributors": [
"zhangsan",
"lisi"
]
}
funding
在開源領域,資金是一個長期存在的問題.
funding命令的作用是讓維護 npm 的開發(fā)人員(為 Node.js 創(chuàng)建包)聲明元數據捏境,為有意愿的捐贈者指明捐贈平臺于游。
在 package.json 文件中添加了一個funding 字段, 可指向在線捐贈服務的 url垫言,如 Patreon贰剥、Open Collective、GitHub Sponsors筷频、License Zero 或者其他支付網站蚌成。
{
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/ant-design"
}
}
files
描述了將軟件包作為依賴項安裝時要包括的條目,默認值為[“*”]凛捏,這意味著它將包括所有文件担忧。
如果需要把打包后的代碼也發(fā)布到 NPM 倉庫
{
"files": ["dist/**/*", "lib/**/*"]
}
你還可以在包的根目錄或子目錄中提供.npmignore 文件,以防止某些文件被發(fā)布坯癣。
.npmignore 文件的工作原理與.gitignore 一樣瓶盛。
如果存在.gitignore 文件,而缺少.npmignore示罗,則將改用.gitignore 的內容惩猫。
files字段內容會覆蓋.npmignore 和.gitignore的內容。
main
main 字段是 package.json 中的另一種元數據功能蚜点,它可以用來指定加載的入口文件轧房。
假如你的項目是一個 npm 包,當用戶安裝你的包后禽额,require('my-module') 返回的是 main 字段中所列出文件的 module.exports 屬性锯厢。
當不指定main 字段時皮官,默認值是模塊根目錄下面的 index.js 文件。
{
"main": "lib/index.js"
}
browserslist
指定該模板供瀏覽器使用的版本实辑。Browserify 這樣的瀏覽器打包工具捺氢,通過它就知道該打包那個文件。
{
"browserslist": [
"> 0.5%",
"last 2 versions",
"Firefox ESR",
"not dead",
"IE 11",
"not IE 10"
]
}
bin
用于將某些可執(zhí)行 Javascript 文件公開給父包的字段剪撬。 此處列出的所有條目都可以通過$ PATH 獲得摄乒。
通俗點理解就是我們全局安裝, 我們就可以在命令行中執(zhí)行這個文件残黑, 本地安裝我們可以在當前工程目錄的命令行中執(zhí)行該文件馍佑。
"bin": {
"my-bin": "./dist/my-bin.js",
}
dist/my-bin.js
#!/usr/bin/env node
console.log("cool");
repository
{
"repository": {
"type": "git",
"url": "https://github.com/ant-design/ant-design"
}
}
scripts
該字段用于列出在運行 yarn run 時將要執(zhí)行的小型 shell 腳本。
請注意梨水,包含:(冒號)的腳本是項目的全局變量拭荤,無論你當前的工作空間如何,都可以調用它們疫诽。
最后舅世,請注意,腳本總是相對于最近的工作空間(而不是 cwd)執(zhí)行奇徒。
"scripts": {
"test": "jest",
"build:dev": "webpack-cli --config ./webpack.dev.config.js",
"build:test": "webpack-cli --config ./webpack.test.config.js",
"build:pro": "webpack-cli --config ./webpack.pro.config.js"
}
NPM 腳本的原理
npm 腳本的原理非常簡單雏亚。每當執(zhí)行 npm run,就會自動新建一個 Shell摩钙,在這個 Shell 里面執(zhí)行指定的腳本命令罢低。因此,只要是 Shell(一般是 Bash)可以運行的命令胖笛,就可以寫在 npm 腳本里面网持。
比較特別的是,npm run 新建的這個 Shell长踊,會將當前目錄的 node_modules/.bin 子目錄加入 PATH 變量翎碑,執(zhí)行結束后,再將 PATH 變量恢復原樣之斯。
這意味著,當前目錄的 node_modules/.bin 子目錄里面的所有腳本遣铝,都可以直接用腳本名調用佑刷,而不必加上路徑。比如酿炸,當前項目的依賴里面有 Mocha瘫絮,只要直接寫 mocha test 就可以了。
"test": "mocha test"
而不用寫成下面這樣填硕。
"test": "./node_modules/.bin/mocha test"
由于 npm 腳本的唯一要求就是可以在 Shell 執(zhí)行麦萤,因此它不一定是 Node 腳本鹿鳖,任何可執(zhí)行文件都可以寫在里面。
npm 腳本的退出碼壮莹,也遵守 Shell 腳本規(guī)則翅帜。如果退出碼不是0,npm 就認為這個腳本執(zhí)行失敗命满。
config
{
"name": "foo",
"config": {
"port": "8080"
}
}
當執(zhí)行npm start命令涝滴,就會引用 npm_package_config_port 環(huán)境變量,
如上面的配置npm start時胶台,就會通過端口8080啟動
但是用戶可以通過執(zhí)行例如 npm config set foo:port 8001 來覆蓋config配置歼疮。
dependencies
應用依賴,或者叫做業(yè)務依賴/生產環(huán)境依賴诈唬,這是我們最常用的依賴包管理對象韩脏!它用于指定應用依賴的外部包,這些依賴是應用發(fā)布后正常執(zhí)行時所需要的铸磅,但不包含測試時或者本地打包時所使用的包
{
"dependencies": {
"react": "^16.9.0",
"react-dom": "^16.9.0"
}
}
放置生產環(huán)境依賴包的地方赡矢,即執(zhí)行項目的 npm run build 時需要的依賴包。因此不要把開發(fā)環(huán)境的依賴包放在這里,比如
- eslint
- typesctipt
- webpack-dev-server
……
因為會增加生產環(huán)境安裝依賴的時間
devDependencies
與dependencies字段類似愚屁,但這些依賴項僅在本地開發(fā)環(huán)境中安裝济竹,而不會由軟件包的使用者(生產環(huán)境)安裝。
開發(fā)環(huán)境依賴霎槐,僅次于dependencies的使用頻率送浊!它的作用和dependencies一樣,只不過它里面的包只用于開發(fā)環(huán)境丘跌,不用于生產環(huán)境袭景,這些包通常是單元測試或者打包工具等,例如gulp, webpack, moca等
{
"devDependencies": {
"webpack": "^4.40.2",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.8.1"
}
}
放置開發(fā)環(huán)境依賴包的地方闭树,即執(zhí)行項目的 npm start 時需要的依賴包耸棒。因此不要把生產環(huán)境的依賴包放在這里
peerDependencies
peerDependencies 的目的是提示宿主環(huán)境去安裝滿足插件 peerDependencies 所指定依賴的包,然后在插件 import 或者 require 所依賴的包的時候报辱,永遠都是引用宿主環(huán)境統(tǒng)一安裝的 NPM 包与殃,最終解決插件與所依賴包不一致的問題。
舉個例子,ant-design UI 組件庫要求宿主環(huán)境安裝指定的 React 版本碍现。具體可以看它的 package.json配置
{
"peerDependencies": {
"react": ">=16.9.0",
"react-dom": ">=16.9.0"
}
}
optionalDependencies
除非你依賴于 fsevents 軟件包幅疼,否則通常不需要此字段。
如果僅在使用特定功能時才需要包昼接,請使用可選的對等依賴項爽篷。
{
"optionalDependencies": {
"fsevents": "^5.0.0"
}
}
engines
engines 字段指明了該模塊運行的平臺,比如 Node 的某個版本或者瀏覽器
該字段也可以指定適用的 npm 版本慢睡。
{
"engines": {
"node": ">=12.18.3",
"npm": ">7.0.0"
}
}
private
如果為 true逐工,則該程序包被視為私有程序,Yarn/NPM 會在任何情況下均拒絕發(fā)布該程序包铡溪。這防止私人存儲庫意外發(fā)布
{
"private": true
}
publishConfig
此字段包含各種設置,僅當從本地來源生成包時才考慮這些設置(通過 yarn pack 或像 yarn npm publish 這樣的發(fā)布命令之一)泪喊。
publishConfig.access定義將程序包發(fā)布到 npm 注冊表時要使用的程序包訪問級別棕硫。 有效值是公開的并且是受限制的,但是受限制的通常需要注冊付費計劃(這取決于你使用的注冊表)窘俺。
publishConfig.bin如果存在饲帅,則在打包打包以將其運送到遠程注冊表之前,清單中的頂級 bin 字段將被設置為此新值瘤泪。 這不會修改真正的清單灶泵,只會修改存儲在 tarball 中的清單。
publishConfig.browser與publishConfig.bin屬性的原理相同对途; 生成工作空間 tarball 時赦邻,將使用此值代替頂級瀏覽器字段。
publishConfig.executableFiles默認情況下实檀,出于可移植性的原因惶洲,在 bin 字段中列出的文件之外的文件都不會在結果包歸檔文件中標記為可執(zhí)行文件。 executeFiles 字段使你可以聲明必須設置了可執(zhí)行標志(+ x)的其他字段膳犹,即使不能通過 bin 字段直接訪問它們也是如此恬吕。
publishConfig.main與publishConfig.bin屬性相同的原理; 生成工作空間 tarball 時须床,將使用此值代替頂級“ main”字段铐料。
publishConfig.module與publishConfig.bin屬性相同的原理; 生成工作空間 tarball 時豺旬,將使用此值代替頂級“ module”字段钠惩。
publishConfig.registry如果存在,當將包推送到遠程位置時族阅,將替換配置中定義的任何注冊表篓跛。
可能的值
{
"publishConfig": {
"access": "public",
"bin": "./build/bin.js",
"browser": "./build/browser.js",
"executableFiles": ["./dist/shim.js"],
"main": "./build/index.js",
"module": "./build/index.mjs",
"registry": "https://npm.pkg.github.com"
}
}
workspaces
工作區(qū)是 monorepos 用來將一個大型項目拆分為半獨立子項目的一項可選功能,每個子項目都列出了自己的一組依賴關系坦刀。 工作區(qū)字段是全局模式列表愧沟,這些模式與應成為應用程序工作區(qū)的所有目錄匹配。
{
"workspaces": ["packages/*"]
}
type
可能的值
- commonjs(默認值),適用于 Node.js 環(huán)境(服務端)
- module,即 ES Module 語法,適用于瀏覽器環(huán)境(客戶端)
無論使用什么值鲤遥,當使用 PnP 時央渣,Yarn 3+都會生成一個.pnp.cjs 文件。
{
"type": "commonjs"
}
main 字段通常用于指向 UMD 版本的庫/包,一般指定為 webpack/rollup 打包 UMD 版本后的路徑
UMD 是什么呢渴频?
- CommonJS + AMD 的組合(即 CommonJS 的語法 + AMD 的異步加載)
- 可以用于 AMD/CommonJS 環(huán)境
- UMD 還支持全局變量定義。因此北启,UMD 模塊能夠在 客戶端和服務器 上工作卜朗。
main 字段還可以在發(fā)布時通過使用 publishConfig.main 字段來修改拔第。
module
與 ES6 兼容的環(huán)境嘗試通過其名稱訪問程序包時將使用的路徑。
module 字段用于指向 ES 版本的庫/包,一般指定為 webpack/rollup 打包 ES 版本后的路徑
{
"module": "es/index.js"
}
unpkg
unpkg 是一個內容源自 npm 的全球快速 CDN
配置unpkg 字段后,發(fā)布到 npmjs.com 中的包會自動同步到 unpkg.com 上场钉,一般為 umd 格式蚊俺。
{
"unpkg": "dist/antd.min.js"
}
typings
{
"typings": "lib/index.d.ts"
}
sideEffects
與 webpack 相關的字段,聲明該模塊是否包含 sideEffects(副作用),從而可以為 tree-shaking 提供更大的優(yōu)化空間逛万。
{
"sideEffects": ["dist/*", "es/**/style/*", "lib/**/style/*", "*.less"]
}