今天來看看前端的大管家 package.json 文件相關的配置,充分了解這些配置有助於我們提高開發的效率,規范我們的項目。文章內容較多,建議先收藏在學習!
在每個前端項目中,都有 package.json 文件,它是項目的配置文件,常見的配置有配置項目啟動、打包命令,聲明依賴包等。package.json 文件是一個 JSON 對象,該對象的每一個成員就是當前項目的一項設置。package.json 作為前端的大管家,到底有哪些配置和我們的日常開發密切相關?下面就來仔細剖析一下這個文件。
當我們搭建一個新項目時,往往腳手架就幫我們初始化好了一個 package.jaon 配置文件,它位於項目的根目錄中。當使用 react 腳手架(create-react-app)初始化一個項目時,其 package.json 文件內容如下:
{ "name": "my-app", "version": "0.1.0", "private": true, "dependencies": { "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^11.2.7", "@testing-library/user-event": "^12.8.3", "react": "^17.0.2", "react-dom": "^17.0.2", "react-scripts": "4.0.3", "web-vitals": "^1.1.2" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { "extends": [ "react-app", "react-app/jest" ] }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } }
當我們克隆一個新的項目到本地時,需要執行 npm install(yarn install)命令來安裝項目所需的依賴文件。當執行該命令時,就會根據 package.json 文件中的配置信息來自動下載所需的模塊,也就是配置項目所需的運行和開發環境。
package.json 常見配置項如下:

package.json 中最重要的兩個字段就是 name 和 version,它們都是必須的,如果沒有,就無法正常執行 npm install 命令。npm 規定 package.json 文件是由名稱和版本號作為唯一標識符的。
1、name
name 很容易理解,就是項目的名稱,它是一個字符串。在給 name 字段命名時,需要注意以下幾點:
(1)名稱的長度必須小於或等於 214 個字符,不能以 “.” 和“_”開頭,不能包含大寫字母(這是因為當軟件包在 npm 上發布時,會基於此屬性獲得自己的 URL,所以不能包含非 URL 安全字符(non-url-safe));
(2)名稱可以作為參數被傳入 require(""),用來導入模塊,所以應當盡可能的簡短、語義化;
(3)名稱不能和其他模塊的名稱重復,可以使用 npm view 命令查詢模塊名是否重復,如果不重復就會提示 404:

如果 npm 包上有對應的包,則會顯示包的詳細信息:

實際上,我們平時開發的很多項目並不會發布在 npm 上,所以這個名稱是否標准可能就不是那么重要,它不會影響項目的正常運行。如果需要發布在 npm 上,name 字段一定要符合要求。
2、version
version 字段表示該項目包的版本號,它是一個字符串。在每次項目改動后,即將發布時,都要同步的去更改項目的版本號。版本號的使用規范如下:
(1)版本號的命名遵循語義化版本 2.0.0 規范,格式為:「主版本號. 次版本號. 修訂號」,通常情況下,修改主版本號是做了大的功能性的改動,修改次版本號是新增了新功能,修改修訂號就是修復了一些 bug;
(2)如果某個版本的改動較大,並且不穩定,可能如法滿足預期的兼容性需求,就需要發布先行版本,先行版本通過會加在版本號的后面,通過 “-” 號連接以點分隔的標識符和版本編譯信息:內部版本(alpha)、公測版本(beta)和候選版本(rc,即 release candiate)
可以通過以下命令來查看 npm 包的版本信息,以 react 為例:
// 查看最新版本 npm view react version // 查看所有版本 npm view react versions 復制代碼
當執行第二條命令時,結果如下:

package.jaon 中有五個和項目包描述信息相關的配置字段,下面就分別來看看這些字段的含義。
1、description
description 字段是用來描述這個項目包,他是一個字符串,可以讓其他的開發着再 npm 的時候發現我們的項目包。
2、keywords
keywords 字段是一個字符串數組,表示這個項目包的關鍵詞,和 description 一樣,都是用來增加項目包的曝光率的,下面是 eslint 包的描敘和關鍵詞:

3、author
author 顧名思義就是作者,表示該項目包的作者。它有兩種形式,一種是字符串格式:
"author": "CUGGZ <xxxxx@xx.com> (https://juejin.cn/user/3544481220801815)"
另一種是對象形式:
"author": { "name" : "CUGGZ", "email" : "xxxxx@xx.com", "url" : "https://juejin.cn/user/3544481220801815" }
4、contributors
contributors 表示該項目包的貢獻者,和 author 不同的是,該字段是一個數組,包含所有的貢獻者,它同樣有兩種寫法:
"contributors": [ "CUGGZ0 <xxxxx@xx.com> (https://juejin.cn/user/3544481220801815)", "CUGGZ1 <xxxxx@xx.com> (https://juejin.cn/user/3544481220801815)" ]
"contributors": [ { "name" : "CUGGZ0", "email" : "xxxxx@xx.com", "url" : "https://juejin.cn/user/3544481220801815" }, { "name" : "CUGGZ1", "email" : "xxxxx@xx.com", "url" : "https://juejin.cn/user/3544481220801815" } ]
5、homepage
homepage 就是項目的主頁地址了,它是一個字符串。
6、repository
repository 表示代碼的存放倉庫地址,通常有兩種書寫形式。第一種是字符串形式:
"repository": "https://github.com/facebook/react.git"
7、bugs
bugs 表示項目提交問題的地址,該字段是一個對象,可以添加一個提交問題的地址和反饋的郵箱:
"bugs": { "url" : "https://github.com/facebook/react/issues", "email" : "xxxxx@xx.com" }
最常見的 bugs 就是 Github 中的 issues 頁面,如上就是 react 的 issues 頁面地址。
通常情況下,我們的項目會依賴一個或者多個外部的依賴包,根據依賴包的不同用途,可以將他們配置在下面的五個屬性下:dependencies、devDependencies、peerDependencies、bundledDependencies、optionalDependencies 。下面就來看看每個屬性的含義。
1、dependencies
dependencies 字段中聲明的是項目的生產環境中所必須的依賴包。當使用 npm 或 yarn 安裝 npm 包時,該 npm 包會被自動插入到此配置項中:
npm install <PACKAGENAME>
yarn add <PACKAGENAME>
當在安裝依賴時使用 --save 參數,也會將新安裝的 npm 包寫入 dependencies 屬性。
npm install --save <PACKAGENAME>
該字段的值是一個對象,該對象的各個成員,分別由模塊名和對應的版本要求組成,表示依賴的模塊及其版本范圍。
"dependencies": { "react": "^17.0.2", "react-dom": "^17.0.2", "react-scripts": "4.0.3", },
這里每一項配置都是一個鍵值對(key-value), key 表示模塊名稱,value 表示模塊的版本號。版本號遵循「主版本號. 次版本號. 修訂號」的格式規定:
- 「固定版本:」 上面的 react-scripts 的版本 4.0.3 就是固定版本,安裝時只安裝這個指定的版本;
- 「波浪號:」 比如~ 4.0.3,表示安裝 4.0.x 的最新版本(不低於 4.0.3),也就是說安裝時不會改變主版本號和次版本號;
- 「插入號:」 比如上面 react 的版本 ^17.0.2,表示安裝 17.x.x 的最新版本(不低於 17.0.2),也就是說安裝時不會改變主版本號。如果主版本號為 0,那么插入號和波浪號的行為是一致的;
- latest:安裝最新的版本。
需要注意,不要把測試或者過渡性的依賴放在 dependencies,避免生產環境出現意外的問題。
2、devDependencies
devDependencies 中聲明的是開發階段需要的依賴包,如 Webpack、Eslint、Babel 等,用於輔助開發。它們不同於 dependencies,因為它們只需安裝在開發設備上,而無需在生產環境中運行代碼。當打包上線時並不需要這些包,所以可以把這些依賴添加到 devDependencies 中,這些依賴依然會在本地指定 npm install 時被安裝和管理,但是不會被安裝到生產環境中。
當使用 npm 或 yarn 安裝軟件包時,指定以下參數后,新安裝的 npm 包會被自動插入到此列表中:
npm install --save-dev <PACKAGENAME>
yarn add --dev <PACKAGENAME>
"devDependencies": { "autoprefixer": "^7.1.2", "babel-core": "^6.22.1" }
3、peerDependencies
有些情況下,我們的項目和所依賴的模塊,都會同時依賴另一個模塊,但是所依賴的版本不一樣。比如,我們的項目依賴 A 模塊和 B 模塊的 1.0 版,而 A 模塊本身又依賴 B 模塊的 2.0 版。大多數情況下,這不是問題,B 模塊的兩個版本可以並存,同時運行。但是,有一種情況,會出現問題,就是這種依賴關系將暴露給用戶。
最典型的場景就是插件,比如 A 模塊是 B 模塊的插件。用戶安裝的 B 模塊是 1.0 版本,但是 A 插件只能和 2.0 版本的 B 模塊一起使用。這時,用戶要是將 1.0 版本的 B 的實例傳給 A,就會出現問題。因此,需要一種機制,在模板安裝的時候提醒用戶,如果 A 和 B 一起安裝,那么 B 必須是 2.0 模塊。
peerDependencies 字段就是用來供插件指定其所需要的主工具的版本。
"name": "chai-as-promised", "peerDependencies": { "chai": "1.x" }
上面代碼指定在安裝 chai-as-promised 模塊時,主程序 chai 必須一起安裝,而且 chai 的版本必須是 1.x。如果項目指定的依賴是 chai 的 2.0 版本,就會報錯
4、optionalDependencies
如果需要在找不到包或者安裝包失敗時,npm 仍然能夠繼續運行,則可以將該包放在 optionalDependencies 對象中,optionalDependencies 對象中的包會覆蓋 dependencies 中同名的包,所以只需在一個地方進行設置即可。
需要注意,由於 optionalDependencies 中的依賴可能並未安裝成功,所以一定要做異常處理,否則當獲取這個依賴時,如果獲取不到就會報錯。
5、bundledDependencies
上面的幾個依賴相關的配置項都是一個對象,而 bundledDependencies 配置項是一個數組,數組里可以指定一些模塊,這些模塊將在這個包發布時被一起打包。
需要注意,這個字段數組中的值必須是在 dependencies, devDependencies 兩個里面聲明過的包才行。
6、engines
當我們維護一些舊項目時,可能對 npm 包的版本或者 Node 版本有特殊要求,如果不滿足條件就可能無法將項目跑起來。為了讓項目開箱即用,可以在 engines 字段中說明具體的版本號:
"engines": { "node": ">=8.10.3 <12.13.0", "npm": ">=6.9.0" }
需要注意,engines 只是起一個說明的作用,即使用戶安裝的版本不符合要求,也不影響依賴包的安裝。
四、腳本配置
1、scripts
scripts 是 package.json 中內置的腳本入口,是 key-value 鍵值對配置,key 為可運行的命令,可以通過 npm run 來執行命令。除了運行基本的 scripts 命令,還可以結合 pre 和 post 完成前置和后續操作。先來看一組 scripts:
"scripts": { "dev": "node index.js", "predev": "node beforeIndex.js", "postdev": "node afterIndex.js" }
這三個 js 文件中都有一句 console:
// index.js console.log("scripts: index.js") // beforeIndex.js console.log("scripts: before index.js") // afterIndex.js console.log("scripts: after index.js")
當我們執行 npm run dev 命令時,輸出結果如下:
scripts: before index.js
scripts: index.js
scripts: after index.js
可以看到,三個命令都執行了,執行順序是 predev→dev→postdev。如果 scripts 命令存在一定的先后關系,則可以使用這三個配置項,分別配置執行命令。
通過配置 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 XXX 或 yarn XXX 來運行它們,其中 XXX 是命令的名稱。例如:npm run dev。我們可以為命令使用任何的名稱,腳本也可以是任何操作。
使用好該字段可以大大的提升開發效率。
2、config
config 字段用來配置 scripts 運行時的配置參數,如下所示:
"config": { "port": 3000 }
如果運行 npm run start,則 port 字段會映射到 npm_package_config_port環境變量中:
console.log(process.env.npm_package_config_port) // 3000
用戶可以通過npm config set foo:port 3001 命令來重寫 port 的值。
五、文件&目錄
下面來看看 package.json 中和文件以及目錄相關的屬性。
1、main
main 字段用來指定加載的入口文件,在 browser 和 Node 環境中都可以使用。如果我們將項目發布為 npm 包,那么當使用 require 導入 npm 包時,返回的就是 main 字段所列出的文件的 module.exports 屬性。如果不指定該字段,默認是項目根目錄下的 index.js。如果沒找到,就會報錯。
該字段的值是一個字符串:
"main": "./src/index.js",
2、borwser
browser 字段可以定義 npm 包在 browser 環境下的入口文件。如果 npm 包只在 web 端使用,並且嚴禁在 server 端使用,使用 browser 來定義入口文件。
"browser": "./src/index.js"
3、module
module 字段可以定義 npm 包的 ESM 規范的入口文件,browser 環境和 node 環境均可使用。如果 npm 包導出的是 ESM 規范的包,使用 module 來定義入口文件。
"module": "./src/index.mjs",
需要注意,.js 文件是使用 commonJS 規范的語法 (require('xxx')),.mjs 是用 ESM 規范的語法 (import 'xxx')。
上面三個的入口入口文件相關的配置是有差別的,特別是在不同的使用場景下。在 Web 環境中,如果使用 loader 加載 ESM(ES module),那么這三個配置的加載順序是 browser→module→main,如果使用 require 加載 CommonJS 模塊,則加載的順序為 main→module→browser。
Webpack 在進行項目構建時,有一個 target 選項,默認為 Web,即構建 Web 應用。如果需要編譯一些同構項目,如 node 項目,則只需將 webpack.config.js 的 target 選項設置為 node 進行構建即可。如果在 Node 環境中加載 CommonJS 模塊,或者 ESM,則只有 main 字段有效。
4、bin
bin 字段用來指定各個內部命令對應的可執行文件的位置:
"bin": { "someTool": "./bin/someTool.js" }
這里,someTool 命令對應的可執行文件為 bin 目錄下的 someTool.js,someTool.js 會建立符號鏈接 node_modules/.bin/someTool。由於 node_modules/.bin / 目錄會在運行時加入系統的 PATH 變量,因此在運行 npm 時,就可以不帶路徑,直接通過命令來調用這些腳本。因此,下面的寫法可以簡寫:
scripts: { start: './node_modules/bin/someTool.js build' } // 簡寫 scripts: { start: 'someTool build' }
所有 node_modules/.bin / 目錄下的命令,都可以用 npm run [命令] 的格式運行。
上面的配置在 package.json 包中提供了一個映射到本地文件名的 bin 字段,之后 npm 包將鏈接這個文件到 prefix/fix 里面,以便全局引入。或者鏈接到本地的 node_modules/.bin / 文件中,以便在本項目中使用。
5、files
files 配置是一個數組,用來描述當把 npm 包作為依賴包安裝時需要說明的文件列表。當 npm 包發布時,files 指定的文件會被推送到 npm 服務器中,如果指定的是文件夾,那么該文件夾下面所有的文件都會被提交。
"files": [ "LICENSE", "Readme.md", "index.js", "lib/" ]
如果有不想提交的文件,可以在項目根目錄中新建一個. npmignore 文件,並在其中說明不需要提交的文件,防止垃圾文件推送到 npm 上。這個文件的形式和. gitignore 類似。寫在這個文件中的文件即便被寫在 files 屬性里也會被排除在外。比如可以在該文件中這樣寫:
node_modules
.vscode
build
.DS_Store
6、man
man 命令是 Linux 中的幫助指令,通過該指令可以查看 Linux 中的指令幫助、配置文件幫助和編程幫助等信息。如果 node.js 模塊是一個全局的命令行工具,在 package.json 通過 man 屬性可以指定 man 命令查找的文檔地址:
"man": [ "./man/npm-access.1", "./man/npm-audit.1" ]
man 字段可以指定一個或多個文件, 當執行 man {包名} 時, 會展現給用戶文檔內容。
需要注意:
- man 文件必須以數字結尾,如果經過壓縮,還可以使用. gz 后綴。這個數字表示文件安裝到哪個 man 節中;
- 如果 man 文件名稱不是以模塊名稱開頭的,安裝的時候會加上模塊名稱前綴。
對於上面的配置,可以使用以下命令來執行查看文檔:
man npm-access
man npm-audit
7、directories
directories 字段用來規范項目的目錄。node.js 模塊是基於 CommonJS 模塊化規范實現的,需要嚴格遵循 CommonJS 規范。模塊目錄下除了必須包含包項目描述文件 package.json 以外,還需要包含以下目錄:
- bin :存放可執行二進制文件的目錄
- lib :存放 js 代碼的目錄
- doc :存放文檔的目錄
- test :存放單元測試用例代碼的目錄
- ...
在實際的項目目錄中,我們可能沒有按照這個規范進行命名,那么就可以在 directories 字段指定每個目錄對應的文件路徑:
"directories": { "bin": "./bin", "lib": "./lib", "doc": "./doc", "test" "./test", "man": "./man" },
這個屬性實際上沒有什么實際的作用,當然不排除未來會有什么比較有意義的用處。
六、發布配置
下面來看看和 npm 項目包發布相關的配置。
1、private
private 字段可以防止我們意外地將私有庫發布到 npm 服務器。只需要將該字段設置為 true:
"private": true
2、preferGlobal
preferGlobal 字段表示當用戶不把該模塊安裝為全局模塊時,如果設置為 true 就會顯示警告。它並不會真正的防止用戶進行局部的安裝,只是對用戶進行提示,防止產生誤解:
"preferGlobal": true
3、 publishConfig
publishConfig 配置會在模塊發布時生效,用於設置發布時一些配置項的集合。如果不想模塊被默認標記為最新,或者不想發布到公共倉庫,可以在這里配置 tag 或倉庫地址。更詳細的配置可以參考 npm-config[1]。
通常情況下,publishConfig 會配合 private 來使用,如果只想讓模塊發布到特定 npm 倉庫,就可以這樣來配置:
"private": true, "publishConfig": { "tag": "1.1.0", "registry": "https://registry.npmjs.org/", "access": "public" }
4、os
os 字段可以讓我們設置該 npm 包可以在什么操作系統使用,不能再什么操作系統使用。如果我們希望開發的 npm 包只運行在 linux,為了避免出現不必要的異常,建議使用 Windows 系統的用戶不要安裝它,這時就可以使用 os 配置:
"os" ["linux"] // 適用的操作系統 "os" ["!win32"] // 禁用的操作系統
5、cpu
該配置和 OS 配置類似,用 CPU 可以更准確的限制用戶的安裝環境:
"cpu" ["x64", "AMD64"] // 適用的cpu "cpu" ["!arm", "!mips"] // 禁用的cpu
可以看到,黑名單和白名單的區別就是,黑名單在前面加了一個 “!”。
6、license
license 字段用於指定軟件的開源協議,開源協議表述了其他人獲得代碼后擁有的權利,可以對代碼進行何種操作,何種操作又是被禁止的。常見的協議如下:
- MIT :只要用戶在項目副本中包含了版權聲明和許可聲明,他們就可以拿你的代碼做任何想做的事情,你也無需承擔任何責任。
- Apache :類似於 MIT ,同時還包含了貢獻者向用戶提供專利授權相關的條款。
- GPL :修改項目代碼的用戶再次分發源碼或二進制代碼時,必須公布他的相關修改。
可以這樣來聲明該字段:
"license": "MIT"
七、第三方配置
package.json 文件還可以承載命令特有的配置,例如 Babel、ESLint 等。它們每個都有特有的屬性,例如 eslintConfig、babel 等。它們是命令特有的,可以在相應的命令 / 項目文檔中找到如何使用它們。下面來看幾個常用的第三方配置項。
1、typings
typings 字段用來指定 TypeScript 的入口文件:
"typings": "types/index.d.ts",
該字段的作用和 main 配置相同。
2、eslintConfig
eslint 的配置可以寫在單獨的配置文件. eslintrc.json 中,也可以寫在 package.json 文件的 eslintConfig 配置項中。
"eslintConfig": { "root": true, "env": { "node": true }, "extends": [ "plugin:vue/essential", "eslint:recommended" ], "rules": {}, "parserOptions": { "parser": "babel-eslint" }, }
3、babel
babel 用來指定 Babel 的編譯配置,代碼如下:
"babel": { "presets": ["@babel/preset-env"], "plugins": [...] }
4、unpkg
使用該字段可以讓 npm 上所有的文件都開啟 cdn 服務,該 CND 服務由 unpkg 提供:
"unpkg": "dist/vue.js"
5、lint-staged
lint-staged 是一個在 Git 暫存文件上運行 linters 的工具,配置后每次修改一個文件即可給所有文件執行一次 lint 檢查,通常配合 gitHooks 一起使用。
"lint-staged": { "*.js": [ "eslint --fix", "git add" ] }
使用 lint-staged 時,每次提交代碼只會檢查當前改動的文件。
6、gitHooks
gitHooks 用來定義一個鈎子,在提交(commit)之前執行 ESlint 檢查。在執行 lint 命令后,會自動修復暫存區的文件。修復之后的文件並不會存儲在暫存區,所以需要用 git add 命令將修復后的文件重新加入暫存區。在執行 pre-commit 命令之后,如果沒有錯誤,就會執行 git commit 命令:
"gitHooks": { "pre-commit": "lint-staged" }
這里就是配合上面的 lint-staged 來進行代碼的檢查操作。
7、browserslist
browserslist 字段用來告知支持哪些瀏覽器及版本。Babel、Autoprefixer 和其他工具會用到它,以將所需的 polyfill 和 fallback 添加到目標瀏覽器。比如最上面的例子中的該字段值:
"browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }
這里指定了一個對象,里面定義了生產環境和開發環境的瀏覽器要求。上面的 development 就是指定開發環境中支持最后一個版本的 chrome、Firefox、safari 瀏覽器。這個屬性是不同的前端工具之間共用目標瀏覽器和 node 版本的配置工具,被很多前端工具使用,比如 Babel、Autoprefixer 等。
轉自:https://mp.weixin.qq.com/s/Vq2UNY-2k65jOevfLpyTGg
