package.json 詳解

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

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

目標(biāo)

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

了解 package.json

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

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)用它來識別你的項目并了解如何處理項目的依賴關(guān)系。package.json 文件使 npm 可以啟動你的項目、運行腳本、安裝依賴項、發(fā)布到 NPM 注冊表以及許多其他有用的任務(wù)。 npm CLI 也是管理 package.json 的最佳方法,因為它有助于在項目的整個生命周期內(nèi)生成和更新 package.json 文件。
package.json 會在項目的生命周期中扮演多個角色,其中某些角色僅適用于發(fā)布到 NPM 的軟件包。即使你沒有把項目發(fā)布到 NPM 注冊表中,或者沒有將其公開發(fā)布給其他人,那么 package.json 對于開發(fā)流程仍然至關(guān)重要。
你的項目還必須包含 package.json,然后才能從 NPM 安裝軟件包。這可能是你在項目中需要它的主要原因之一。

package.json 中的常見字段

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

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

name

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

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

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

name 規(guī)范

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

version

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

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

version 規(guī)范

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

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

詳細內(nèi)容參考語義化版本 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

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

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

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

homepage

項目主頁 url,默認值為/

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

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

bugs

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

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

license

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

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

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


{
  "license": "MIT"
}

詳細內(nèi)容參考

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

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

funding

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

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

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

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

files

描述了將軟件包作為依賴項安裝時要包括的條目,默認值為[“*”],這意味著它將包括所有文件。

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

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

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

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

main

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

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

當(dāng)不指定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 獲得。

通俗點理解就是我們?nèi)职惭b, 我們就可以在命令行中執(zhí)行這個文件, 本地安裝我們可以在當(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

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

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

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

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

這意味著,當(dāng)前目錄的 node_modules/.bin 子目錄里面的所有腳本,都可以直接用腳本名調(diào)用,而不必加上路徑。比如,當(dā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 就認為這個腳本執(zhí)行失敗。

config

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

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

dependencies

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

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

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

  • eslint
  • typesctipt
  • webpack-dev-server
    ……
    因為會增加生產(chǎn)環(huán)境安裝依賴的時間

devDependencies

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

開發(fā)環(huán)境依賴,僅次于dependencies的使用頻率!它的作用和dependencies一樣,只不過它里面的包只用于開發(fā)環(huán)境,不用于生產(chǎ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 時需要的依賴包。因此不要把生產(chǎn)環(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

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

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

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

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

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

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

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

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

可能的值

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

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

type

可能的值

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

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

{
  "type": "commonjs"
}

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

UMD 是什么呢?

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

module

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

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

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

unpkg

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

配置unpkg 字段后,發(fā)布到 npmjs.com 中的包會自動同步到 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)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

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