關於前端大管家 package-json,你知道多少?

今天來看看前端的大管家 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 字段命名時,需要注意以下幾點:

如果 npm 包上有對應的包,則會顯示包的詳細信息:實際上,我們平時開發的很多項目並不會發佈在 npm 上,所以這個名稱是否標準可能就不是那麼重要,它不會影響項目的正常運行。如果需要發佈在 npm 上,name 字段一定要符合要求。

2. version

version 字段表示該項目包的版本號,它是一個字符串。在每次項目改動後,即將發佈時,都要同步的去更改項目的版本號。版本號的使用規範如下:

可以通過以下命令來查看 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"

除此之外,還可以顯式地設置版本控制系統,這時就是對象的形式:

"repository"{
  "type""git",
  "url""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 表示模塊的版本號。版本號遵循主版本號. 次版本號. 修訂號的格式規定:

需要注意,不要把測試或者過渡性的依賴放在 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 版本,就會報錯。

需要注意,從 npm 3.0 版開始,peerDependencies 不再會默認安裝了。

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. browser

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 npm-access
man npm-audit

7. directories

directories 字段用來規範項目的目錄。node.js 模塊是基於 CommonJS 模塊化規範實現的,需要嚴格遵循 CommonJS 規範。模塊目錄下除了必須包含包項目描述文件 package.json 以外,還需要包含以下目錄:

在實際的項目目錄中,我們可能沒有按照這個規範進行命名,那麼就可以在 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。

通常情況下,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 字段用於指定軟件的開源協議,開源協議表述了其他人獲得代碼後擁有的權利,可以對代碼進行何種操作,何種操作又是被禁止的。常見的協議如下:

可以這樣來聲明該字段:

"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 等。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/fxX4oPHURDpvFvCIZUd7VA