package.json 詳解

Node 項(xiàng)目在項(xiàng)目根目錄中名為 package.json 的文件中跟蹤依賴關(guān)系和元數(shù)據(jù)。這是你項(xiàng)目的核心。它包含名稱、描述和版本之類的信息,以及運(yùn)行、開發(fā)以及有選擇地將項(xiàng)目發(fā)布到 NPM 所需的信息。
在本教程中,我們將:

  • 了解 package.json 與項(xiàng)目之間的關(guān)系
  • 確定重要字段和元數(shù)據(jù)
  • 了解如何管理 package.json

目標(biāo)

了解什么是 package.json 文件,它與你項(xiàng)目的關(guān)系以及需要了解的常見屬性。

了解 package.json

如果你以前用過 Node.js,則可能會(huì)遇到 package.json 文件。它是一個(gè) JSON 文件,位于項(xiàng)目的根目錄中。你的 package.json 包含關(guān)于項(xiàng)目的重要信息。它包含關(guān)于項(xiàng)目的使人類可讀元數(shù)據(jù)(如項(xiàng)目名稱和說明)以及功能元數(shù)據(jù)(如程序包版本號(hào)和程序所需的依賴項(xiàng)列表)。

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 的用途是什么?

項(xiàng)目的 package.json 是配置和描述如何與程序交互和運(yùn)行的中心。 npm CLI(和 yarn)用它來識(shí)別你的項(xiàng)目并了解如何處理項(xiàng)目的依賴關(guān)系。package.json 文件使 npm 可以啟動(dòng)你的項(xiàng)目、運(yùn)行腳本、安裝依賴項(xiàng)、發(fā)布到 NPM 注冊(cè)表以及許多其他有用的任務(wù)。 npm CLI 也是管理 package.json 的最佳方法,因?yàn)樗兄谠陧?xiàng)目的整個(gè)生命周期內(nèi)生成和更新 package.json 文件。
package.json 會(huì)在項(xiàng)目的生命周期中扮演多個(gè)角色,其中某些角色僅適用于發(fā)布到 NPM 的軟件包。即使你沒有把項(xiàng)目發(fā)布到 NPM 注冊(cè)表中,或者沒有將其公開發(fā)布給其他人,那么 package.json 對(duì)于開發(fā)流程仍然至關(guān)重要。
你的項(xiàng)目還必須包含 package.json,然后才能從 NPM 安裝軟件包。這可能是你在項(xiàng)目中需要它的主要原因之一。

package.json 中的常見字段

讓我們看一下 package.json 中包含的一些最常見和重要的字段,以更好地了解如何使用和管理這個(gè)基本文件。有些用來發(fā)布到 NPM,而其他一些則可以幫助 npm CLI 運(yùn)行應(yīng)用程序或安裝依賴項(xiàng)。

實(shí)際的字段比我們所介紹的要多,你可以在它的文檔中了解其余字段,但以下的是必須要了解的 package.json 屬性。

name

package.json 中最重要的屬性是 nameversion 兩個(gè)屬性,這兩個(gè)屬性是必須要有的,否則模塊就無法被安裝,這兩個(gè)屬性一起形成了一個(gè) npm 模塊的唯一標(biāo)識(shí)。

name是 package(包)的名稱。名稱的第一部分(如@scope/是可選的,用作名稱空間)。當(dāng)我們的包發(fā)布到 NPM 網(wǎng)站,其他人才能通過搜索name來安裝使用

{
  "name": "@scope/name"
}

name 規(guī)范

  • 最好取簡(jiǎn)短而語義化的值
  • 不能以,.開頭
  • 不能有大寫字母/空格/下滑線!
  • 不能和 NPM 網(wǎng)站中已有的包名字重名!

version

version是 package(包)的版本,通常,它不會(huì)對(duì)你的項(xiàng)目產(chǎn)生任何影響,

除非它是一個(gè)工作空間(workspaces)-其版本必須與指定的范圍相匹配,才能選擇該工作空間作為解決方案的候選對(duì)象。

version 規(guī)范

version 具體體現(xiàn)為::“x.y.z”

  • 修復(fù) bug,小改動(dòng),增加 z
  • 增加了新特性,但仍能向后兼容,增加 y
  • 有很大的改動(dòng),無法向后兼容,增加 x

詳細(xì)內(nèi)容參考語義化版本 2.0.0

使用 npm version <update_type>自動(dòng)升級(jí)版本號(hào)
update_type為patch, minor, major其中之一,分別表示補(bǔ)丁,小改,大改

npm version patch
npm version minor
npm version major

在 CI(持續(xù)集成)的腳本中可以用到此命令

description

一個(gè)描述,方便別人了解你的模塊作用,搜索的時(shí)候也有用。

{
  "description": "xxxx"
}

keywords

一個(gè)字符串?dāng)?shù)組,方便別人搜索到本模塊

{
  "keywords": [
    "ant",
    "component",
    "design"
  ]
}

當(dāng)我們使用 npm 檢索模塊時(shí),會(huì)對(duì)模塊中的 description 字段和 keywords 字段進(jìn)行匹配,寫好 package.json 中的 description 和 keywords 將有利于增加我們模塊的曝光率。

homepage

項(xiàng)目主頁(yè) url,默認(rèn)值為/

一般來說,我們打包的靜態(tài)資源會(huì)部署在 CDN 上,為了讓我們的應(yīng)用知道去哪里加載資源,則需要我們?cè)O(shè)置一個(gè)根路徑,這時(shí)可以通過 package.json 中的 homepage 字段設(shè)置應(yīng)用的根路徑。

{
  "homepage": "https://ant.design"
}

bugs

填寫一個(gè) bug 提交地址或者一個(gè)郵箱,被你的模塊坑到的人可以通過這里吐槽,例如:

{
  "bugs": {
    "url":"https://github.com/ant-design/ant-design/issues"
  }
}

license

你應(yīng)該為你的開源代碼模塊制定一個(gè)開源協(xié)議,讓用戶知道他們有何權(quán)限來使用你的模塊,以及使用該模塊有哪些限制

  • MIT 是最少約束的選擇。
  • GPL 是最多約束的。

如果是個(gè)人隨意作品,建議 MIT 許可。如果是公司或者需要嚴(yán)格保護(hù)的開源產(chǎn)品,GPL。


{
  "license": "MIT"
}

詳細(xì)內(nèi)容參考

和用戶相關(guān)的屬性: author, contributors

{
  "author": "iikonan",
  "contributors": [
    "zhangsan",
    "lisi"
  ]
}

funding

在開源領(lǐng)域,資金是一個(gè)長(zhǎng)期存在的問題.

funding命令的作用是讓維護(hù) npm 的開發(fā)人員(為 Node.js 創(chuàng)建包)聲明元數(shù)據(jù),為有意愿的捐贈(zèng)者指明捐贈(zèng)平臺(tái)。

在 package.json 文件中添加了一個(gè)funding 字段, 可指向在線捐贈(zèng)服務(wù)的 url,如 Patreon、Open Collective、GitHub Sponsors、License Zero 或者其他支付網(wǎng)站。

{
  "funding": {
    "type": "opencollective",
    "url": "https://opencollective.com/ant-design"
  }
}

files

描述了將軟件包作為依賴項(xiàng)安裝時(shí)要包括的條目,默認(rèn)值為[“*”],這意味著它將包括所有文件。

如果需要把打包后的代碼也發(fā)布到 NPM 倉(cāng)庫(kù)

{
  "files": ["dist/**/*", "lib/**/*"]
}

你還可以在包的根目錄或子目錄中提供.npmignore 文件,以防止某些文件被發(fā)布。

.npmignore 文件的工作原理與.gitignore 一樣。
如果存在.gitignore 文件,而缺少.npmignore,則將改用.gitignore 的內(nèi)容。
files字段內(nèi)容會(huì)覆蓋.npmignore 和.gitignore的內(nèi)容。

main

main 字段是 package.json 中的另一種元數(shù)據(jù)功能,它可以用來指定加載的入口文件。

假如你的項(xiàng)目是一個(gè) npm 包,當(dāng)用戶安裝你的包后,require('my-module') 返回的是 main 字段中所列出文件的 module.exports 屬性。

當(dāng)不指定main 字段時(shí),默認(rèn)值是模塊根目錄下面的 index.js 文件。

{
  "main": "lib/index.js"
}

browserslist

指定該模板供瀏覽器使用的版本。Browserify 這樣的瀏覽器打包工具,通過它就知道該打包那個(gè)文件。

{
  "browserslist": [
    "> 0.5%",
    "last 2 versions",
    "Firefox ESR",
    "not dead",
    "IE 11",
    "not IE 10"
  ]
}

bin

用于將某些可執(zhí)行 Javascript 文件公開給父包的字段。 此處列出的所有條目都可以通過$ PATH 獲得。

通俗點(diǎn)理解就是我們?nèi)职惭b, 我們就可以在命令行中執(zhí)行這個(gè)文件, 本地安裝我們可以在當(dāng)前工程目錄的命令行中執(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

該字段用于列出在運(yùn)行 yarn run 時(shí)將要執(zhí)行的小型 shell 腳本。

請(qǐng)注意,包含:(冒號(hào))的腳本是項(xiàng)目的全局變量,無論你當(dāng)前的工作空間如何,都可以調(diào)用它們。

最后,請(qǐng)注意,腳本總是相對(duì)于最近的工作空間(而不是 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 腳本的原理非常簡(jiǎn)單。每當(dāng)執(zhí)行 npm run,就會(huì)自動(dòng)新建一個(gè) Shell,在這個(gè) Shell 里面執(zhí)行指定的腳本命令。因此,只要是 Shell(一般是 Bash)可以運(yùn)行的命令,就可以寫在 npm 腳本里面。

比較特別的是,npm run 新建的這個(gè) Shell,會(huì)將當(dāng)前目錄的 node_modules/.bin 子目錄加入 PATH 變量,執(zhí)行結(jié)束后,再將 PATH 變量恢復(fù)原樣。

這意味著,當(dāng)前目錄的 node_modules/.bin 子目錄里面的所有腳本,都可以直接用腳本名調(diào)用,而不必加上路徑。比如,當(dāng)前項(xiàng)目的依賴?yán)锩嬗?Mocha,只要直接寫 mocha test 就可以了。

"test": "mocha test"

而不用寫成下面這樣。

"test": "./node_modules/.bin/mocha test"

由于 npm 腳本的唯一要求就是可以在 Shell 執(zhí)行,因此它不一定是 Node 腳本,任何可執(zhí)行文件都可以寫在里面。

npm 腳本的退出碼,也遵守 Shell 腳本規(guī)則。如果退出碼不是0,npm 就認(rèn)為這個(gè)腳本執(zhí)行失敗。

config

{
  "name": "foo",
  "config": {
    "port": "8080"
  }
}

當(dāng)執(zhí)行npm start命令,就會(huì)引用 npm_package_config_port 環(huán)境變量,
如上面的配置npm start時(shí),就會(huì)通過端口8080啟動(dòng)
但是用戶可以通過執(zhí)行例如 npm config set foo:port 8001 來覆蓋config配置。

dependencies

應(yīng)用依賴,或者叫做業(yè)務(wù)依賴/生產(chǎn)環(huán)境依賴,這是我們最常用的依賴包管理對(duì)象!它用于指定應(yīng)用依賴的外部包,這些依賴是應(yīng)用發(fā)布后正常執(zhí)行時(shí)所需要的,但不包含測(cè)試時(shí)或者本地打包時(shí)所使用的包

{
  "dependencies": {
    "react": "^16.9.0",
    "react-dom": "^16.9.0"
  }
}

放置生產(chǎn)環(huán)境依賴包的地方,即執(zhí)行項(xiàng)目的 npm run build 時(shí)需要的依賴包。因此不要把開發(fā)環(huán)境的依賴包放在這里,比如

  • eslint
  • typesctipt
  • webpack-dev-server
    ……
    因?yàn)闀?huì)增加生產(chǎn)環(huán)境安裝依賴的時(shí)間

devDependencies

與dependencies字段類似,但這些依賴項(xiàng)僅在本地開發(fā)環(huán)境中安裝,而不會(huì)由軟件包的使用者(生產(chǎn)環(huán)境)安裝。

開發(fā)環(huán)境依賴,僅次于dependencies的使用頻率!它的作用和dependencies一樣,只不過它里面的包只用于開發(fā)環(huán)境,不用于生產(chǎn)環(huán)境,這些包通常是單元測(cè)試或者打包工具等,例如gulp, webpack, moca等

{
  "devDependencies": {
    "webpack": "^4.40.2",
    "webpack-cli": "^3.3.9",
    "webpack-dev-server": "^3.8.1"
  }
}

放置開發(fā)環(huán)境依賴包的地方,即執(zhí)行項(xiàng)目的 npm start 時(shí)需要的依賴包。因此不要把生產(chǎn)環(huán)境的依賴包放在這里

peerDependencies

peerDependencies 的目的是提示宿主環(huán)境去安裝滿足插件 peerDependencies 所指定依賴的包,然后在插件 import 或者 require 所依賴的包的時(shí)候,永遠(yuǎn)都是引用宿主環(huán)境統(tǒng)一安裝的 NPM 包,最終解決插件與所依賴包不一致的問題。

舉個(gè)例子,ant-design UI 組件庫(kù)要求宿主環(huán)境安裝指定的 React 版本。具體可以看它的 package.json配置

{
  "peerDependencies": {
    "react": ">=16.9.0",
    "react-dom": ">=16.9.0"
  }
}

optionalDependencies

除非你依賴于 fsevents 軟件包,否則通常不需要此字段。

如果僅在使用特定功能時(shí)才需要包,請(qǐng)使用可選的對(duì)等依賴項(xiàng)。

{
  "optionalDependencies": {
    "fsevents": "^5.0.0"
  }
}

engines

engines 字段指明了該模塊運(yùn)行的平臺(tái),比如 Node 的某個(gè)版本或者瀏覽器

該字段也可以指定適用的 npm 版本。

{
  "engines": {
    "node": ">=12.18.3",
    "npm": ">7.0.0"
  }
}

private

如果為 true,則該程序包被視為私有程序,Yarn/NPM 會(huì)在任何情況下均拒絕發(fā)布該程序包。這防止私人存儲(chǔ)庫(kù)意外發(fā)布

{
  "private": true
}

publishConfig

此字段包含各種設(shè)置,僅當(dāng)從本地來源生成包時(shí)才考慮這些設(shè)置(通過 yarn pack 或像 yarn npm publish 這樣的發(fā)布命令之一)。

publishConfig.access定義將程序包發(fā)布到 npm 注冊(cè)表時(shí)要使用的程序包訪問級(jí)別。 有效值是公開的并且是受限制的,但是受限制的通常需要注冊(cè)付費(fèi)計(jì)劃(這取決于你使用的注冊(cè)表)。

publishConfig.bin如果存在,則在打包打包以將其運(yùn)送到遠(yuǎn)程注冊(cè)表之前,清單中的頂級(jí) bin 字段將被設(shè)置為此新值。 這不會(huì)修改真正的清單,只會(huì)修改存儲(chǔ)在 tarball 中的清單。

publishConfig.browser與publishConfig.bin屬性的原理相同; 生成工作空間 tarball 時(shí),將使用此值代替頂級(jí)瀏覽器字段。

publishConfig.executableFiles默認(rèn)情況下,出于可移植性的原因,在 bin 字段中列出的文件之外的文件都不會(huì)在結(jié)果包歸檔文件中標(biāo)記為可執(zhí)行文件。 executeFiles 字段使你可以聲明必須設(shè)置了可執(zhí)行標(biāo)志(+ x)的其他字段,即使不能通過 bin 字段直接訪問它們也是如此。

publishConfig.main與publishConfig.bin屬性相同的原理; 生成工作空間 tarball 時(shí),將使用此值代替頂級(jí)“ main”字段。

publishConfig.module與publishConfig.bin屬性相同的原理; 生成工作空間 tarball 時(shí),將使用此值代替頂級(jí)“ module”字段。

publishConfig.registry如果存在,當(dāng)將包推送到遠(yuǎn)程位置時(shí),將替換配置中定義的任何注冊(cè)表。

可能的值

{
  "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 用來將一個(gè)大型項(xiàng)目拆分為半獨(dú)立子項(xiàng)目的一項(xiàng)可選功能,每個(gè)子項(xiàng)目都列出了自己的一組依賴關(guān)系。 工作區(qū)字段是全局模式列表,這些模式與應(yīng)成為應(yīng)用程序工作區(qū)的所有目錄匹配。

{
  "workspaces": ["packages/*"]
}

type

可能的值

  • commonjs(默認(rèn)值),適用于 Node.js 環(huán)境(服務(wù)端)
  • module,即 ES Module 語法,適用于瀏覽器環(huán)境(客戶端)

無論使用什么值,當(dāng)使用 PnP 時(shí),Yarn 3+都會(huì)生成一個(gè).pnp.cjs 文件。

{
  "type": "commonjs"
}

main 字段通常用于指向 UMD 版本的庫(kù)/包,一般指定為 webpack/rollup 打包 UMD 版本后的路徑

UMD 是什么呢?

  • CommonJS + AMD 的組合(即 CommonJS 的語法 + AMD 的異步加載)
  • 可以用于 AMD/CommonJS 環(huán)境
  • UMD 還支持全局變量定義。因此,UMD 模塊能夠在 客戶端和服務(wù)器 上工作。
    main 字段還可以在發(fā)布時(shí)通過使用 publishConfig.main 字段來修改。

module

與 ES6 兼容的環(huán)境嘗試通過其名稱訪問程序包時(shí)將使用的路徑。

module 字段用于指向 ES 版本的庫(kù)/包,一般指定為 webpack/rollup 打包 ES 版本后的路徑

{
  "module": "es/index.js"
}

unpkg

unpkg 是一個(gè)內(nèi)容源自 npm 的全球快速 CDN

配置unpkg 字段后,發(fā)布到 npmjs.com 中的包會(huì)自動(dòng)同步到 unpkg.com 上,一般為 umd 格式。

{
  "unpkg": "dist/antd.min.js"
}

typings

{
  "typings": "lib/index.d.ts"
}

sideEffects

與 webpack 相關(guān)的字段,聲明該模塊是否包含 sideEffects(副作用),從而可以為 tree-shaking 提供更大的優(yōu)化空間。

{
  "sideEffects": ["dist/*", "es/**/style/*", "lib/**/style/*", "*.less"]
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Node 項(xiàng)目在項(xiàng)目根目錄中名為 package.json 的文件中跟蹤依賴關(guān)系和元數(shù)據(jù)。這是你項(xiàng)目的核心。它包含...
    Axtlive閱讀 1,345評(píng)論 0 2
  • 當(dāng)我們創(chuàng)建一個(gè) Node 項(xiàng)目時(shí), 需要?jiǎng)?chuàng)建一個(gè) package.json 文件,描述這個(gè)項(xiàng)目所需要的各種模塊,以...
    lio_zero閱讀 763評(píng)論 0 5
  • 本文是對(duì) Node.js 項(xiàng)目中 package.json 文件的詳解。 目錄 package.json 簡(jiǎn)介 配...
    又語閱讀 2,423評(píng)論 0 1
  • package.json 可以通過 npm init 來交互式地創(chuàng)建。package.json 中可寫的內(nèi)容非常多...
    One_Hund閱讀 1,404評(píng)論 0 1
  • 這里只截取了部分常用的選項(xiàng),全部?jī)?nèi)容戳這里 概述 注意package.json必須是純JSON的,而不僅僅是一個(gè)J...
    葉夏星辰閱讀 1,894評(píng)論 0 0

友情鏈接更多精彩內(nèi)容