package.json 檔案是基於 Node.js 生態系統的許多應用程式原碼中的重要元素。如果你有在使用 JavaScript 或者曾經與 JavaScript 專案、Node.js 或者前端專案互動過,那麼你肯定遇到過 package.json
檔案。
那它有什麼作用呢?你應該知道哪些內容呢?你可以用它做哪些很酷的事情呢?
package.json
檔案可以說是你專案的宣告文件。它可以做很多種完全不相關的事情。它是工具的集中配置中心。它還是 npm
和 yarn
存儲安裝套件的名稱和版本的地方。
檔案結構
這裡是一個 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.jsbrowserslist
用於告訴你想要支援的瀏覽器及其版本
所有這些屬性都是被 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 XXXX
或 yarn 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 等等。
每個命令都有一個特定的屬性,例如 eslintConfig
、babel
等等。這些都是特定於命令的,您可以在相應的命令/專案文檔中找到如何使用它們的內容。
套件版本
您在上述描述中看到了版本號,例如 ~3.0.0
或 ^0.13.0
。它們是什麼意思,您還可以使用哪些其他版本規範?
該符號指定了您的套件接受的依賴更新範圍。
考慮到使用語義化版本(semantic versioning)所有版本的版本號都有三個數字,分別是主版本號、次版本號和修訂版本號,您有以下規則:
~
:如果您寫了~0.13.0
,則表示您只想更新修訂版本:0.13.1
是可以的,但0.14.0
則不行。^
:如果您寫了^0.13.0
,則表示您想要更新修訂和次要版本:0.13.1
、0.14.0
等等。*
:如果您寫了*
,這意味著您接受所有更新,包括主要版本升級。>
:接受大於指定版本的任何版本。>=
:接受等於或高於指定版本的任何版本。<=
:接受等於或低於指定版本的任何版本。<
:接受低於指定版本的任何版本。
還有其他規則:
- 沒有符號:僅接受您指定的特定版本。
latest
:您希望使用最新版本。
您還可以將上述大多數組合在範圍內,例如:1.0.0 || >=1.1.0 <1.2.0
,要么使用 1.0.0,要么使用 1.1.0 或更高版本,但要低於 1.2.0。