package.json 檔案是基於 Node.js 生態系統的許多應用程式原碼中的重要元素。如果你有在使用 JavaScript 或者曾經與 JavaScript 專案、Node.js 或者前端專案互動過,那麼你肯定遇到過 package.json 檔案。

那它有什麼作用呢?你應該知道哪些內容呢?你可以用它做哪些很酷的事情呢?

package.json 檔案可以說是你專案的宣告文件。它可以做很多種完全不相關的事情。它是工具的集中配置中心。它還是 npmyarn 存儲安裝套件的名稱和版本的地方。

檔案結構

這裡是一個 package.json 檔案的例子:

{

}

它是空的!對於應用程式而言,package.json 檔案中沒有固定的要求。唯一的要求是符合 JSON 格式,否則它無法被程式讀取與存取其屬性。

如果你正在建立一個希望在 npm 上分發的 Node.js 套件,事情就會發生很大的變化,你必須具備一系列的屬性,以幫助其他人使用它。稍後我們會進一步瞭解。

這是另一個 package.json 檔案的例子:

{
 "name": "test-project"
}

它定義了一個 name 屬性,該屬性告訴我們應用程式或者套件名稱,並且與該檔案所在的資料夾相同。

這是一個更複雜的範例,我從示例 Vue.js 應用程式中提取出來的:

{
 "name": "test-project",
 "version": "1.0.0",
 "description": "A Vue.js project",
 "main": "src/main.js",
 "private": true,
 "scripts": {
 "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
 "start": "npm run dev",
 "unit": "jest --config test/unit/jest.conf.js --coverage",
 "test": "npm run unit",
 "lint": "eslint --ext .js,.vue src test/unit",
 "build": "node build/build.js"
 },
 "dependencies": {
 "vue": "^2.5.2"
 },
 "devDependencies": {
 "autoprefixer": "^7.1.2",
 "babel-core": "^6.22.1",
 "babel-eslint": "^8.2.1",
 "babel-helper-vue-jsx-merge-props": "^2.0.3",
 "babel-jest": "^21.0.2",
 "babel-loader": "^7.1.1",
 "babel-plugin-dynamic-import-node": "^1.2.0",
 "babel-plugin-syntax-jsx": "^6.18.0",
 "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
 "babel-plugin-transform-runtime": "^6.22.0",
 "babel-plugin-transform-vue-jsx": "^3.5.0",
 "babel-preset-env": "^1.3.2",
 "babel-preset-stage-2": "^6.22.0",
 "chalk": "^2.0.1",
 "copy-webpack-plugin": "^4.0.1",
 "css-loader": "^0.28.0",
 "eslint": "^4.15.0",
 "eslint-config-airbnb-base": "^11.3.0",
 "eslint-friendly-formatter": "^3.0.0",
 "eslint-import-resolver-webpack": "^0.8.3",
 "eslint-loader": "^1.7.1",
 "eslint-plugin-import": "^2.7.0",
 "eslint-plugin-vue": "^4.0.0",
 "extract-text-webpack-plugin": "^3.0.0",
 "file-loader": "^1.1.4",
 "friendly-errors-webpack-plugin": "^1.6.1",
 "html-webpack-plugin": "^2.30.1",
 "jest": "^22.0.4",
 "jest-serializer-vue": "^0.3.0",
 "node-notifier": "^5.1.2",
 "optimize-css-assets-webpack-plugin": "^3.2.0",
 "ora": "^1.2.0",
 "portfinder": "^1.0.13",
 "postcss-import": "^11.0.0",
 "postcss-loader": "^2.0.8",
 "postcss-url": "^7.2.1",
 "rimraf": "^2.6.0",
 "semver": "^5.3.0",
 "shelljs": "^0.7.6",
 "uglifyjs-webpack-plugin": "^1.1.1",
 "url-loader": "^0.5.8",
 "vue-jest": "^1.0.2",
 "vue-loader": "^13.3.0",
 "vue-style-loader": "^3.0.1",
 "vue-template-compiler": "^2.5.2",
 "webpack": "^3.6.0",
 "webpack-bundle-analyzer": "^2.9.0",
 "webpack-dev-server": "^2.9.1",
 "webpack-merge": "^4.1.0"
 },
 "engines": {
 "node": ">= 6.0.0",
 "npm": ">= 3.0.0"
 },
 "browserslist": [
 "> 1%",
 "last 2 versions",
 "not ie <= 8"
 ]
}

這裡有很多事情需要注意的地方:

  • name 設置 應用程式/套件 名稱
  • version 表示當前版本
  • description 是對應用程式/套件的簡要說明
  • main 設置應用程式的入口點
  • private 如果設置為 true,則防止該應用程式/套件被意外地發佈到 npm
  • scripts 定義了一組你可以運行的節點指令碼
  • dependencies 設置了依賴的 npm 套件列表
  • devDependencies 設置了作為開發依賴的 npm 套件列表
  • engines 設置此套件/應用程式適用於哪些版本的 Node.js
  • browserslist 用於告訴你想要支援的瀏覽器及其版本

所有這些屬性都是被 npm 或其他工具使用的。

屬性解析

本節為詳細描述你可以使用的屬性。我提到了“套件”,但相同的規則也適用於您不將其用作套件的本地應用程式。

這些屬性中的大部分僅在 https://www.npmjs.com/ 上使用,其他則由與代碼互動的腳本如 npm 或其他工具使用。

name

設置套件名稱。

範例:

"name": "test-project"

名稱必須小於214個字符,不得包含空格,只能包含小寫字母、連字符(-)或底線(_)。

這是因為當套件在 npm 上發佈時,它將基於此屬性獲得其自己的 URL。

如果您公開在 GitHub 上發佈此套件,則此屬性的好值可以是 GitHub 存儲庫名稱。

author

列出套件作者的名字。

範例:

{
 "author": "Flavio Copes <[[email protected]](/cdn-cgi/l/email-protection)> (https://flaviocopes.com)"
}

也可以使用以下格式:

{
 "author": {
 "name": "Flavio Copes",
 "email": "[[email protected]](/cdn-cgi/l/email-protection)",
 "url": "https://flaviocopes.com"
 }
}

contributors

除了作者外,該專案還可能有一個或多個貢獻者。這個屬性是一個列舉他們的數組。

範例:

{
 "contributors": [
 "Flavio Copes <[[email protected]](/cdn-cgi/l/email-protection)> (https://flaviocopes.com)"
 ]
}

也可以使用以下格式:

{
 "contributors": [
 {
 "name": "Flavio Copes",
 "email": "[[email protected]](/cdn-cgi/l/email-protection)",
 "url": "https://flaviocopes.com"
 }
 ]
}

bugs

鏈接到套件問題跟踪器,通常是 GitHub 的問題頁面。

範例:

{
 "bugs": "https://github.com/flaviocopes/package/issues"
}

homepage

設置套件首頁。

範例:

{
 "homepage": "https://flaviocopes.com/package"
}

version

指定套件的當前版本。

範例:

"version": "1.0.0"

該屬性遵從語義化版本(semantic versioning, semver)表示法,這意味著版本始終以 3 個數字表示:x.x.x

第一個數字是主版本號,第二個數字是次版本號,第三個數字是修訂版本號。

這些數字的含義:僅修復錯誤的發布是修訂版本,引入向後兼容更改的發布是次要版本,具有破壞性變化的發布是主要版本。

license

指示套件的授權。

範例:

"license": "MIT"

keywords

此屬性包含一個關聯的關鍵字數組,用於描述您的套件所做的事情。

範例:

"keywords": [
 "email",
 "machine learning",
 "ai"
]

當導航類似套件或瀏覽 https://www.npmjs.com/ 網站時,這有助於人們找到您的套件。

description

此屬性包含套件的簡短描述。

範例:

"description": "A package to work with strings"

如果您決定將您的套件發佈到 npm,這對於讓人們了解套件是關於什麼非常有用。

repository

此屬性指定套件庫所在的位置。

範例:

"repository": "github:flaviocopes/testing",

注意到 github 前缀。還有其他受歡迎的服務內建:

"repository": "gitlab:flaviocopes/testing",
"repository": "bitbucket:flaviocopes/testing",

您可以明確地設置版本控制系統:

"repository": {
 "type": "git",
 "url": "https://github.com/flaviocopes/testing.git"
}

您可以使用不同的版本控制系統:

"repository": {
 "type": "svn",
 "url": "..."
}

main

將該套件的入口點設置為指定的位置。

當您在應用程式中導入該套件時,應用程式將搜尋模塊導出的位置。

範例:

"main": "src/main.js"

private

如果設置為 true,將防止意外地將該應用程式/套件發佈到 npm

範例:

"private": true

scripts

定義了一組您可以運行的節點指令碼。

範例:

"scripts": {
 "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
 "start": "npm run dev",
 "unit": "jest --config test/unit/jest.conf.js --coverage",
 "test": "npm run unit",
 "lint": "eslint --ext .js,.vue src test/unit",
 "build": "node build/build.js"
}

這些腳本是命令行應用程序。您可以通過調用 npm run XXXXyarn XXXX 運行它們,其中 XXXX 是命令名。例如:npm run dev

您可以對命令使用任何您想要的名稱,並且腳本可以做任何您想要的事情。

dependencies

設置作為依賴項安裝的 npm 套件列表。

當您使用 npm 或 yarn 安裝套件時:

npm install <PACKAGENAME>
yarn add <PACKAGENAME>

該套件會自動插入到此列表中。

範例:

"dependencies": {
 "vue": "^2.5.2"
}

devDependencies

設置安裝為開發依賴項的 npm 套件列表。

dependencies 不同,它們僅在開發機器上安裝,並在生產代碼中不需要。

當您使用 npm 或 yarn 安裝套件時:

npm install --dev <PACKAGENAME>
yarn add --dev <PACKAGENAME>

該套件會自動插入到此列表中。

範例:

"devDependencies": {
 "autoprefixer": "^7.1.2",
 "babel-core": "^6.22.1"
}

engines

設置此套件/應用程式適用於哪些版本的 Node.js 和其他命令。

範例:

"engines": {
 "node": ">= 6.0.0",
 "npm": ">= 3.0.0",
 "yarn": "^0.13.0"
}

browserslist

用於告訴你想要支援的瀏覽器以及他們的版本。Babel、Autoprefixer 和其他工具使用它,僅將 polyfill 和回退部分添加到你所針對的瀏覽器。

範例:

"browserslist": [
 "> 1%",
 "last 2 versions",
 "not ie <= 8"
]

此配置意味著您希望支援所有瀏覽器的最新 2 個主要版本,其使用率至少為 1%(根據 CanIUse.com 統計),除去 IE8 和更低版本。

了解更多

特定命令屬性

package.json 檔案還可以承載特定於命令的配置,例如 Babel、ESLint 等等。

每個命令都有一個特定的屬性,例如 eslintConfigbabel 等等。這些都是特定於命令的,您可以在相應的命令/專案文檔中找到如何使用它們的內容。

套件版本

您在上述描述中看到了版本號,例如 ~3.0.0^0.13.0。它們是什麼意思,您還可以使用哪些其他版本規範?

該符號指定了您的套件接受的依賴更新範圍。

考慮到使用語義化版本(semantic versioning)所有版本的版本號都有三個數字,分別是主版本號、次版本號和修訂版本號,您有以下規則:

  • ~:如果您寫了 ~0.13.0,則表示您只想更新修訂版本:0.13.1 是可以的,但 0.14.0 則不行。
  • ^:如果您寫了 ^0.13.0,則表示您想要更新修訂和次要版本:0.13.10.14.0 等等。
  • *:如果您寫了 *,這意味著您接受所有更新,包括主要版本升級。
  • >:接受大於指定版本的任何版本。
  • >=:接受等於或高於指定版本的任何版本。
  • <=:接受等於或低於指定版本的任何版本。
  • <:接受低於指定版本的任何版本。

還有其他規則:

  • 沒有符號:僅接受您指定的特定版本。
  • latest:您希望使用最新版本。

您還可以將上述大多數組合在範圍內,例如:1.0.0 || >=1.1.0 <1.2.0,要么使用 1.0.0,要么使用 1.1.0 或更高版本,但要低於 1.2.0。