package.json詳解

草履蟲的思考發表於2020-04-04

前言

簡述寫這篇文章的原因:

寫這篇文章是因為前段時間有人問我,她在面試中面試官問了她,是否瞭解package.json中的版本問題?安裝模組的~>^等代表什麼意思?她跟我說,平時只是用專案中的npm start啟動或者構建專案,真沒有一個個瞭解這麼多,當時心態就崩了o(╥﹏╥)oo(╥﹏╥)o,後面面試也沒能答好。

我給的建議就是,在面試中或者平時遇到難題這都很正常,前端問題很多很難都面面俱到,都是一個成長的過程,這個時候我們就實話說,說沒有具體瞭解,回去後我去補補這方面的知識,或者去請教面試官,都是可以的,也不會因為這一個問題就pass你。面試官會考察這方便的問題,一方面是根據自己業務中遇到過這些問題,還有就是考察面試者掌握前端的基礎和深度廣度,我們真不知道的時候,傳達給面試官我們有學習的探索精神。

目標:你從本文可以學到什麼?

  • 1、關於npm
  • 2、package.json是什麼?
  • 3、如何建立package.json
  • 4、全域性安裝和本地安裝到底是怎麼區分的?
  • 5、安裝、更新、解除安裝模組
  • 6、package.json中模組的版本^2.0.0``~2.0.0等 (安裝版本使用到@表示什麼意思?npm install jquery@3.4.1
  • 7、package.json中每個欄位的詳解
  • 8、版本號version的意義,如,大更新、增加一些功能上線、修補一些小布丁的上線,我們改怎麼打包版本號?與git如何配合使用
  • 9、版本號的週期、階段,(-alpha、-beta、-rc都是什麼週期的哪個階段專案,哪些是開發人員打包的專案,哪些是測試人員的專案,上線的專案)
  • 10、一些其他的npm命令
  • 11、瞭解package.json與專案直接的關係
  • 12、require引入模組的時候是怎麼查詢模組的

在講解package.json時,必須要先簡單介紹一下npm,那npm是什麼呢?要怎麼安裝呢?

npm

npm 是前端開發廣泛使用的包管理工具, 為您和您的團隊開啟了整個JavaScript的世界。 來自各大洲的開源開發人員使用npm來共享和借用包,許多組織也使用npm來管理私有開發。

1、npm是什麼?

官方介紹:

npm makes it easy for JavaScript developers to share and reuse code, and it makes it easy to update the code that you’re sharing.

ps: 官方網站 www.npmjs.com/ 瀏覽、搜尋、下載安裝想要的別人上傳的模組,也可以直接在命令列中 search 一下。

我們程式開發中常常需要依賴別人提供的框架,我們可以看到一些大型的vue、react框架中也是有依賴別人的模組或者說是包,這樣可以提高效率,避免重複造輪子,且往往這些輪子使用者體驗也必比較好。一個包或者說模組都會有一個package.json檔案用來描述這個包。

使用npm,我們可以更方便檢視依賴這些模組的更新。

npm都幹什麼了呢?

npm由三個不同的元件組成:

  • 網站: www.npmjs.com/
  • 命令列介面(CLI):開發者使用它來管理、安裝、更新、釋出模組;
  • 登錄檔:儲存著人們分享的js模組的大資料庫

2、安裝npm

從node.js站點安裝npm

第一步:安裝node.js和npm

在這裡不具體講解安裝過程了,網上有很多。 npm 是依附於 node.js 的,我們可以去它的官網 nodejs.org/en/download… 下載安裝 node.js。

第二步:測試您的安裝

安裝後,執行node -v。沒有報錯,出現版本號為成功。安裝node.js是,會自動安裝npm。同樣執行npm -v,可檢視版本號。

package.json詳解

第三步:如果你需要更新npm

npm 更新地可比 node 勤快多了,因此你下載的 node 附帶的 npm 版本可能不是最新的,你可以使用如下命令下載最新 npm:

npm install npm@latest -g
複製程式碼

在這講解一下這句話的意思

  • install:就表示是要安裝;
  • npm@latest: 使用 @ 的格式,表示作用域,指定版本,latest表示最新模板;我們在下載其他模組時也是這個格式。
  • -g:表示全域性安裝

安裝 -g 是全域性安裝,可以在任意命令下使用,如:

npm i http-server -g
複製程式碼

> 我們在命令列中http-server可以在命令中使用,是因為我們配置了環境變數.

/usr/local/bin/http-server -> /usr/local/lb/node_modules/http-server/bin/http-server

3、安裝npm軟體包(全域性或本地)

package.json

管理本地安裝的npm包的最佳方法是建立一個 package.json檔案。

瞭解package.json

每個專案(npm上下載的包,或者其他的nodejs專案)的根目錄下面,一般都有一個package.json檔案, 定義了這個專案所需要的各種模組,以及專案的配置資訊(比如名稱、版本、許可證、如何啟動專案、執行腳步等後設資料)。npm install命令根據這個配置檔案,自動下載所需的模組。

package.json檔案就是一個JSON物件,該物件的每一個成員就是當前專案的一項設定。比如name就是專案名稱,version是版本(遵守“大版本.次要版本.小版本”的格式)。還會在專案的生命週期中扮演多個角色、開發、測試、上線版本。

package.json的作用

  • 作為一個描述檔案,描述了你的專案所依賴的包
  • 允許我們使用 “語義化版本規則”(後面介紹)指明你專案依賴包的版本
  • 讓你的構建更好地與其他開發者分享,便於重複使用

package.json如何建立

1、使用命令列工具客戶端CLI

npm init
複製程式碼

這將啟動命令列調查問卷,該調查問卷將package.json在您啟動命令的目錄中建立.

package.json詳解

2、建立預設值

要獲取預設值package.json,請npm init使用--yes or -y標誌執行:

 npm init -y
複製程式碼

此方法將package.json使用從當前目錄中提取的資訊生成預設值, 跳過回答問題步驟 。

package.json詳解

3、手動建立

直接在專案根目錄新建一個 package.json 檔案,然後輸入相關的內容。 具體請檢視package.json的注意事項。

package.json檔案常見欄位詳解

1、 name

必須欄位 ,當前模組\包名稱, 長度必須小於等於214個字元,不能以"."(點)或者"_"(下劃線)開頭,不能包含大寫字母。

這個名字可能會作為引數被傳入require(),所以它應該比較短,但也要意義清晰。

2、 version

必須欄位 ,當前包的版本號,初次建立預設為1.0.0

version必須可以被npm依賴的一個node-semver模組解析 。定義了當前專案的版本迭代進度。 (遵守“大版本.次要版本.小版本”的格式)

可能現在很多小夥伴們沒有注意或者不在乎版本號,更多使用產品的版本號,或者git hashcode方式。

3、 description

可選欄位,必須是字串。當前包的描述資訊,是一個字串。它可以幫助人們在使用npm search時找到這個包。

如果 package.json 中沒有 description 資訊,npm 使用專案中的 README.md 的第一行作為描述資訊。這個描述資訊有助於別人搜尋你的專案,因此建議好好寫 description 資訊。

4、 main

可選欄位, 指定了專案載入的入口檔案。

這個欄位的預設值是模組根目錄下面的index.js

5、 scripts

可選欄位,scripts是一個由指令碼命令組成的hash物件,他們在包不同的生命週期中被執行。key是生命週期事件,value是要執行的命令。 指定了執行指令碼命令的npm命令列縮寫,比如start指定了執行npm run start時,所要執行的命令。我們可以自定義我們想要的執行腳步命令。

參考: www.ruanyifeng.com/blog/2016/1…

scripts配置執行的腳步

  • 1)執行命令 echo xxx

    1. 執行node_modules/.bin 下的檔案

為什麼可以執行呢?

當我執行 npm run的時候,就會自動新建一個 Shell,在這個 Shell 裡面執行指定的指令碼命令。因此,只要是 Shell(一般是 Bash)可以執行的命令,就可以寫在 npm 指令碼里面。會把當前目錄下的node_modules/.bin也拷貝到當前的系統的path(只是臨時拷貝,執行結束後,在將PATH變數恢復原樣), 所以當前目錄的node_modules/.bin子目錄裡面的所有指令碼,都可以直接用指令碼名呼叫,而不必加上路徑。

例如:

我們用node執行一個node.js服務是,node + 檔案 可以用node server.js; 我們也可以用webpack的打包前端檔案,webpack-dev-server,當然webpack 和webpack-dev-server是要安裝依賴的模組;

"scripts": {   
    "build": "webpack --mode=development",
    "dev": "webpack-dev-server --mode=development --contentBase=./dist",
    "server":"node app.js"
  }
複製程式碼

我們在命令列工具中輸入npm run server ,就會呼叫node app.js幫我們執行。

簡寫形式:

npm start是npm run start
npm stop是npm run stop的簡寫
npm test是npm run test的簡寫
npm restart是npm run stop && npm run restart && npm run start的簡寫
複製程式碼

常用指令碼 -----網上收集轉

// 刪除目錄
"clean": "rimraf dist/*",

// 本地搭建一個 HTTP 服務
"serve": "http-server -p 9090 dist/",

// 開啟瀏覽器
"open:dev": "opener http://localhost:9090",

// 實時重新整理
 "livereload": "live-reload --port 9091 dist/",

// 構建 HTML 檔案
"build:html": "jade index.jade > dist/index.html",

// 只要 CSS 檔案有變動,就重新執行構建
"watch:css": "watch 'npm run build:css' assets/styles/",

// 只要 HTML 檔案有變動,就重新執行構建
"watch:html": "watch 'npm run build:html' assets/html",

// 部署到 Amazon S3
"deploy:prod": "s3-cli sync ./dist/ s3://example-com/prod-site/",

// 構建 favicon
"build:favicon": "node scripts/favicon.js",

"start": "cross-env NODE_ENV=production node server/index.js",

複製程式碼

6、 dependencies、devDependencies

可選欄位, dependencies欄位指定了專案執行所依賴的模組 , devDependencies指定專案開發所需要的模組 。

值指向一個物件。該物件的各個成員,分別由模組名和對應的版本要求組成,表示依賴的模組及其版本範圍。

預設建立的package.json沒有,當我們安裝npm install一個模組時就會生成。

npm install express
npm install express --save
npm install express --save-dev
複製程式碼

上面程式碼表示單獨安裝express模組,

  • 後邊沒有引數時,表示安裝到dependencies屬性,
  • --save參數列示將該模組寫入dependencies屬性,
  • --save-dev表示將該模組寫入devDependencies屬性。

7、bundledDependencies

可選欄位,釋出包時同時打包的其他依賴。

8、 peerDependencies

可選欄位,相容性依賴,如果你的專案或者模組,同時依賴另一個模組,但是所依賴的版本不一樣。

比如,你的專案依賴A模組和B模組的1.0版,而A模組本身又依賴B模組的2.0版。

{
  "name": "chai-as-promised",
  "peerDependencies": {
    "chai": "1.x"
  }
}
複製程式碼

上面程式碼指定,安裝chai-as-promised模組時,主程式chai必須一起安裝,而且chai的版本必須是1.x。如果你的專案指定的依賴是chai的2.0版本,就會報錯。

9、 bin

可選欄位,bin欄位用來指定各個內部命令對應的可執行檔案的位置。

例如: 之前我在寫建立一個自己的腳手架時,也用到了這個。 juejin.im/post/5e1802…

具體使用可檢視,這篇文章的第三步,工程建立。

在專案根目錄建立/bin/www檔案

#! /usr/bin/env node
複製程式碼

package.json中配置

"bin":{
  "lee-cli":"./bin/www"
}
複製程式碼

npm link 將package中的屬性bin的值路徑新增全域性連結 建立快捷方式連線

在命令列中執行lee-cli就會執行bin/www檔案。過程是:

在上面的例子中,www會建立符號連結node_modules/.bin/www。由於node_modules/.bin/目錄會在執行時加入系統的PATH變數,因此在執行npm時,就可以不帶路徑,直接通過命令來呼叫這些指令碼。

10、 config

config欄位用於向環境變數輸出值

{
  "name" : "package",
  "config" : { "port" : "8080" },
  "scripts" : { "start" : "node server.js" }
}
複製程式碼

如果想改變我們可以使用

npm config set package:port 80
複製程式碼

11、engines

可選欄位,指明瞭該模組執行的平臺版本,比如 Node 的某個版本或者瀏覽器, 也可以指定適用的npm版本 。

"engines" : { 
"node" : 
">=0.10.3 <0.12"
} 
複製程式碼

12、license

可選欄位, 表示定義適用於package.json所描述程式碼的許可證。不同的協議有不同的限制。讓使用者知道他們有何許可權來使用你的模組,以及使用該模組有哪些限制。

可參考: choosealicense.com/ 選擇許可證。

如:MIT:最大許可,別人下載你的程式碼可以改你的程式碼,預設安裝值。

13、author

可選欄位,專案開發者。

14、private

可選欄位,布林值,是否私有,設定為 true 時,npm 拒絕釋出。

這是防止私有包被以外發布的一種方法。如果你希望包裝某個包只能被髮布到特定的一個registry中(比如,一個內部的registry),則可以使用下面的publishConfig字典來描述以在publish-time重寫registry配置引數。

15、keywords

可選欄位,專案關鍵字,是一個字串陣列。它可以幫助人們在使用npm search時找到這個包。

16、os

可選欄位,指定模組可以在什麼作業系統上執行

17、style

style指定供瀏覽器使用時,樣式檔案所在的位置。

18、repository

包程式碼存放的地方的型別,可以是 git 或 svn,git 可在 Github 上

19、homepage

可選欄位,沒有http://等帶協議字首的URL。

版本問題:

version:"1.0.0"

1.0.0:

第一位改變表示:不相容老程式碼,大規模的更新,新版本釋出;

第二位表示:增加了一些功能,向下相容;

第三位表示:小的補丁,bug修改;

我們發表專案的時候,一盤使用npm + git

  • 使用npm version patch (patch打補丁) 這種會改變版本的第三位;使用git tag 執行即會自動在git上版本號
  • 使用npm version minor這種改變的版本號的第二位;同步git版本;
  • 使用npm version major 這種改變版本號的第一位;同步git版本;
npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]

major:主版本號

minor:次版本號

patch:補丁號

premajor:預備主版本

prepatch:預備次版本

prerelease:預釋出版本
複製程式碼

ps:注意,如果報錯:Git working directory not clean 是說明你現在需要git status是clean的。

git add .
git commit -m"package.json詳解  "
複製程式碼

npm versin monir

如何制定規則?

作為使用者,我們可以在 package.json 檔案中寫明我們可以接受這個包的更新程度(假設當前依賴的是 1.2.4 版本):

  • 如果只打算接受補丁版本的更新(也就是最後一位的改變),就可以這麼寫:

     1.2
     1.2.x
     ~1.2.4
    複製程式碼
  • 如果接受小版本的更新(第二位的改變),就可以這麼寫:

    1
    1.x
    ^1.2.4
    複製程式碼
  • 如果可以接受大版本的更新(自然接受小版本和補丁版本的改變),就可以這麼寫:

    *
    x
    複製程式碼

    小結一下:總共三種版本變化型別,接受依賴包哪種型別的更新,就把版本號準確寫到前一位。

版本週期、階段:

  • α -Alpha 第一階段 一般只供內測使用
  • β -Beta 第二階段 已經消除了軟體中大部分的不完善之處,但是仍有可能還存在缺陷和漏洞,一般提供給特定的使用者群裡來測試使用;
  • γ - RC 是第三階段,此時產品已經相當成熟,只需要在個別地方在做進一步的優化處理即可上市釋出

例如:

2.1.0-beta.1 一般這樣使用者不會安裝這種的,這種可以用內側、測試人員使用。

依賴包的版本問題

例項 說明
~1.2.3 主版本+次要版本+補丁版本;1.2.3 <= version < 1.3.0;
~1.2 主版本+次要版本;1.2.0 <= version < 1.3.0
~1 主版本;1.0.0 <= version < 2.0.0
符號 例項 版本範圍 說明
1.0.0 1.0.0 鎖定1.0.0版本,必須這個版本。
^會匹配最新的大版本依賴包 ^1.2.3、^0.2.3 >=1.2.3 <2.0.0、>=0.2.3 <0.3.0 表示安裝1.x.x的最新版本(不低於1.2.3,包括1.3.0),但是不安裝2.x.x,也就是說安裝時不改變大版本號。需要注意的是,如果大版本號為0,則插入號的行為與波浪號相同,這是因為此時處於開發階段,即使是次要版本號變動,也可能帶來程式的不相容。(主版本)
~會匹配最近的小版本依賴包 ~1.2.3 >=1.2.3 <1.3.0 表示安裝1.2.x的最新版本(不低於1.2.3),但是不安裝1.3.x,也就是說安裝時不改變大版本號和次要版本號。
>= >=2.1.0 >=2.1.0 大於等於2.1.0
<= <=2.0.0 <=2.0.0 小於等於2.0.0
laster 安裝最新的版本
* >=0.0.0 任何版本
- 1.2.3 - 2.3.4 >=1.2.3 <=2.3.4

區分安裝Dependenciesdependencies

devDependencies是開發所需要的模組,所以我們可以在開發過程中需要的安裝上去,來提高我們的開發效率,比如一些知名的第三方庫, webpackrollUplessbabel這些。 就沒必要在生成環境安裝。

以下類庫都建議安裝到devDependencies:

  • 單元測試支撐(mocha、chai);
  • 語法相容(babel);
  • 語法轉換(jsx to js、coffeescript to js、typescript to js)
  • 程式構建與優化(webpack、gulp、grunt、uglifyJS);
  • css 處理器(postCSS、SCSS、Stylus);
  • 程式碼規範(eslint);

依賴包(指定、更新、本地、使用、解除安裝)

1、安裝本地依賴包

npm install jquery
複製程式碼

這個命令會在當前目錄建立一個 node_modules 目錄,然後下載我們指定的包到這個目錄中。

2、指定安裝版本,可以在package name後@版本號

如果包的名稱以包開頭@,則它是一個範圍包

npm install jquery@3.4.1
npm install jquery@">=1.1.0 <2.2.0"
npm install jquery@latest
複製程式碼

更新之後,dependencies內的版本號也會改變。

3、更新依賴包

npm update jquery
複製程式碼

4、使用包

let jquery = require('jquery');
複製程式碼
<script src="/node_modules/jquery/dist/jquery.js">//這個需要注意路徑</script> 
複製程式碼

6、解除安裝依賴包

npm uninstall jquery
複製程式碼

Semantic versioning(語義化版本規則)

docs.npmjs.com/about-seman…

github.com/npm/node-se…

package.json注意事項

根據上邊我們在使用npm init會詢問我們填幾項內容,有的可以不填,有的必須填,這些必填都是一個package.json內容必須要具備的欄位:nameversion,如果沒有,無法執行install

  • name:全是小寫,沒有空格,循序使用連字元和下劃線
  • version: 版本號,遵循上邊說的語義化版本規則x.x.x

其他注意事項:

  • 新增中文註釋會編譯出錯

延伸

其他

1、我們經常會在安裝一半退出在繼續安裝會報錯,這是因為有快取的原因。

npm cache clean --force
複製程式碼

2、npx

npx可以直接執行node_modules/.bin檔案 不需要在去配置scripts

如果模組不存在可以安裝,安裝完有後會自己銷燬,避免安裝全域性模組

參考資料:

cloud.tencent.com/developer/s…

docs.npmjs.com/about-seman…

semver.org/lang/zh-CN/

docs.npmjs.com/misc/semver…

www.ruanyifeng.com/blog/2016/1…

相關文章