第四節:npm介紹、package.json詳解、npm install原理、常用指令、npx工具、發布自己的包


一. 包管理工具npm

(關於npm的安裝、配置下載路徑、一些指令,可以參考之前的文章:https://www.cnblogs.com/yaopengfei/p/14478126.html)

1. npm簡介

(1). 包管理工具npm

    npm全稱,Node Package Manager,也就是Node包管理器;

    但是目前已經不僅僅是Node包管理器了,在前端項目中我們也在使用它來管理依賴的包;比如vue、vue-router、vuex、express、koa、react、react-dom、axios、babel、webpack等等;

(2).如何下載npm工具呢?

  npm屬於node的一個管理工具,所以我們需要先安裝Node,安裝完node以后,npm也就安裝了。

  node管理工具:https://nodejs.org/en/

(3). npm管理的包可以在哪里查看、搜索呢?

  npm包的官網:https://www.npmjs.com/

(4). npm管理的包存放在哪里呢?

  我們發布自己的包其實是發布到registry上面的;當我們安裝一個包時其實是從registry上面下載的包;

  A. 通過【npm install xxx -g】全局安裝的包,在你設置的全局文件夾下:D:\Develop\npm\node_modules

  B. 通過【npm install xxx】和【npm install -D】安裝項目依賴的包,在對應項目的node_modules里。

注意:對於項目依賴的包,她是有緩存的,即如果本地電腦已經下載過這個版本的包,就直接去本地拿到壓縮包,解壓到項目中的node_modules即可,不需要去npm官網的registry上下載,那么這個壓縮包在 D:\Develop\npm-cache 下。

【后面將結合package_lock.json詳細講解】
 

2. npm配置文件(package.json)

(1). npm如何管理這么多包?

   我們每一個項目都會有一個對應的配置文件,無論是前端項目(Vue、React)還是后端項目(Node);這個配置文件會記錄着你項目的名稱、版本號、項目描述等;也會記錄着你項目所依賴的其他庫的信息和依賴庫的版本號

   這個配置文件就是package.json

(2). 如何生成這個配置文件

  A.  手動從零創建項目,【npm init –y】 或者【npm init】一步一步生成

  B.  通過腳手架創建項目,腳手架會幫助我們生成package.json,並且里面有相關的配置

npm init -y 創建的配置文件

{
  "name": "01_npm",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Vue3的配置文件

{
    "name": "vue3Admin",
    "version": "0.1.0",
    "description": "vue3 vite next admin template js setup",
    "author": "ypf",
    "license": "MIT",
    "scripts": {
        "serve": "vite --force",
        "build": "vite build",
        "lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/"
    },
    "dependencies": {
        "@element-plus/icons-vue": "^0.2.4",
        "axios": "^0.24.0",
        "echarts": "^5.2.2",
        "element-plus": "^1.2.0-beta.6",
        "mitt": "^3.0.0",
        "nprogress": "^0.2.0",
        "qrcodejs2-fixes": "^0.0.2",
        "screenfull": "^6.0.0",
        "sortablejs": "^1.14.0",
        "vue": "3.2.20",
        "vue-clipboard3": "^1.0.1",
        "vue-router": "^4.0.12",
        "vuex": "^4.0.2"
    },
    "devDependencies": {
        "@vitejs/plugin-vue": "^2.0.1",
        "@vue/compiler-sfc": "^3.2.26",
        "dotenv": "^10.0.0",
        "eslint": "^8.5.0",
        "eslint-plugin-vue": "^8.2.0",
        "prettier": "^2.5.1",
        "sass": "^1.45.1",
        "sass-loader": "^12.4.0",
        "unplugin-auto-import": "^0.5.4",
        "vite": "^2.7.4",
        "vite-plugin-vue-setup-extend": "^0.1.0",
        "vue-eslint-parser": "^8.0.1"
    },
    "browserslist": [
        "> 1%", "last 2 versions", "not dead" ], "bugs": { "url": "https://www.cnblogs.com/yaopengfei" }, "engines": { "node": ">=12.0.0", "npm": ">= 6.0.0" }, "keywords": [ "vue", "vue3", "vuejs/vue-next", "vuejs/vue-next-template", "vuejs/vue-next-template-js", "element-ui", "element-plus", "vue-next-admin", "next-admin" ], "repository": { "type": "git", "url": "https://www.cnblogs.com/yaopengfei" } }
View Code

 

3. package.json屬性詳解

(1). 基本屬性

   name是項目的名稱;【必填】

   version是當前項目的版本號;【必填】

   description是描述信息,很多時候是作為項目的基本描述;

   author是作者相關信息(發布時用到);

   license是開源協議(發布時用到);

(2). private屬性

   private屬性記錄當前的項目是否是私有的;

   當值為true時npm是不能發布它的,這是防止私有項目或模塊發布出去的方式;

(3). main屬性

   設置程序的入口。webpack實際上是找到對應的main屬性查找文件的

(4). scripts屬性

    scripts屬性用於配置一些腳本命令,以鍵值對的形式存在;配置后我們可以通過 npm run 命令的key來執行這個命令;

    比如配置了 "serve": "vite --force",  我們就可以執行 【npm run server】 實際上等價於 【npx vite --force

特殊情況:對於常用的key,是可以省略run的。【npm start】和【npm run start】是等價的。對於常用的 start、 test、stop、restart可以省略掉run直接通過 npm start等方式運行;

(5). dependencies屬性

    dependencies屬性是指定無論開發環境還是生產環境都需要依賴的包通常是我們項目實際開發用到的一些庫模塊vue、vuex、vue-router、react、react-dom、axios等等;

(6). devDependencies屬性

    一些包在生產環境是不需要的,僅開發過程中需要,比如webpack、babel等; 這個時候我們會通過 【npm install webpack --save-dev】,將它安裝到devDependencies屬性中;

(7). peerDependencies屬性

    還有一種項目依賴關系是對等依賴,也就是你依賴的一個包,它必須是以另外一個宿主包為前提的; 比如element-plus是依賴於vue3的,ant design是依賴於react、react-dom;

(8). 依賴版本管理【重】

 npm的包通常需要遵從semver版本規范:semver:https://semver.org/lang/zh-CN/   npm semver:https://docs.npmjs.com/misc/semver

 semver版本規范是X.Y.Z: 

   X主版本號(major):當你做了不兼容的 API 修改(可能不兼容之前的版本);

   Y次版本號(minor):當你做了向下兼容的功能性新增(新功能增加,但是兼容之前的版本);

   Z修訂號(patch):當你做了向下兼容的問題修正(沒有新功能,修復了之前版本的bug);

  比如:   "vue": "3.2.20"、“^3.2.20”、“~3.2.20”、

 我們這里解釋一下 ^和~的區別:

  ^x.y.z:表示x是保持不變的,y和z永遠安裝最新的版本;【這里指npm install的時候】

  ~x.y.z:表示x和y保持不變的,z永遠安裝最新的版本;    【這里指npm install的時候】

    x.y.z :  就如字面一樣的版本

(9). engines屬性

  engines屬性用於指定Node和NPM的版本號;

  在安裝的過程中,會先檢查對應的引擎版本,如果不符合就會報錯;

  事實上也可以指定所在的操作系統 "os" : [ "darwin", "linux" ],只是很少用到;

(10). browserslist屬性

   用於配置打包后的JavaScript瀏覽器的兼容情況,參考;否則我們需要手動的添加polyfills來讓支持某些語法;也就是說它是為webpack等打包工具服務的一個屬性

 

二. npm install原理

1. package-lock.json剖析

 下面代碼是執行了【npm install axios】后的文件

{
  "name": "01_npm",
  "version": "1.0.0",
  "lockfileVersion": 2,
  "requires": true,
  "packages": {
    "": {
      "name": "01_npm",
      "version": "1.0.0",
      "license": "ISC",
      "dependencies": {
        "axios": "^0.26.1"
      }
    },
    "node_modules/axios": {
      "version": "0.26.1",
      "resolved": "https://registry.npmmirror.com/axios/-/axios-0.26.1.tgz",
      "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
      "dependencies": {
        "follow-redirects": "^1.14.8"
      }
    },
    "node_modules/follow-redirects": {
      "version": "1.14.9",
      "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.14.9.tgz",
      "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
      "engines": {
        "node": ">=4.0"
      },
      "peerDependenciesMeta": {
        "debug": {
          "optional": true
        }
      }
    }
  },
  "dependencies": {
    "axios": {
      "version": "0.26.1",
      "resolved": "https://registry.npmmirror.com/axios/-/axios-0.26.1.tgz",
      "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
      "requires": {
        "follow-redirects": "^1.14.8"
      }
    },
    "follow-redirects": {
      "version": "1.14.9",
      "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.14.9.tgz",
      "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w=="
    }
  }
}
View Code

name:項目的名稱;

version:項目的版本;

lockfileVersion:lock文件的版本;

requires:使用requires來跟蹤模塊的依賴關系;

dependencies:項目的依賴,當前項目依賴axios,但是axios依賴follow-redireacts;

axios中的屬性如下:

  version表示實際安裝的axios的版本

  resolved用來記錄下載的地址,registry倉庫中的位置;

  requires記錄當前模塊的依賴;

  integrity用來從緩存中獲取索引,再通過索引去獲取壓縮包文件

2. 【npm install】指令原理

npm install首先會檢測是有package-lock.json文件:

(1). 沒有lock文件

  A. 分析依賴關系,這是因為我們可能包會依賴其他的包,並且多個包之間會產生相同依賴的情況;

  B. 從registry倉庫中下載壓縮包(如果我們設置了鏡像,那么會從鏡像服務器下載壓縮包,比如設置了從taobao下載);

  C. 獲取到壓縮包后會對壓縮包進行緩存(從npm5開始有的);

  D. 將壓縮包解壓到項目的node_modules文件夾中(require的查找順序會在該包下面查找)

(2). 有lock文件

 A. 檢測lock中包的版本是否和package.json中一致(會按照semver版本規范檢測,詳見上面08);

 B. 不一致,那么會重新構建依賴關系,直接會走頂層的流程;

 C. 一致的情況下,會去優先查找緩存

 D. 沒有找到,會從registry倉庫下載,直接走頂層流程;

 E. 查找到,會獲取緩存中的壓縮文件,並且將壓縮文件解壓到node_modules文件夾中;

(3). 緩存的作用

  將通過npm下載過的包存放到本地(D:\Develop\npm-cache\_cacache) ,【npm get cache 查找路徑】,下次npm的時候,會先查看package_lock中的版本是否符合package中的版本要求,如果符合,則優先查找緩存。

  如何查找去緩存中查找呢?

  package_lock中的integrity屬性存放的是索引,然后根據索引去對應的文件夾Content-v2中找到壓縮包,然后解壓到項目中去。

 

D:\Develop\npm-cache\_cacache\index-v5   存放索引
D:\Develop\npm-cache\_cacache\content-v2  存放內容

(4). package_lock.json的作用

 A. 鎖定實際版本,用於【npm install】恢復的時候,下載該版本的包。

 B. 記錄包本地緩存的索引,便於查找本地磁盤中的查找壓縮包,來解壓到項目中。

4.  實戰測試

場景1:只有package.json  ,  初始化運行【npm install】

如下,為package.json中的包對應的版本號,此時npm服務器上最新的版本分別為  0.26.1、4.17.21

"dependencies": {
    "axios": "^0.26.0",
    "lodash": "^4.17.20"
  }

運行指令【npm install】,按照規范 y和z處的版本號都要保持最新,所以實際安裝的使 0.26.1 和 4.17.21這一版本 ,如下圖生成的package_lock.json文件中的版本號

 

場景2:存在lock文件,初始化運行【npm install】

如下,為package.json中的包對應的版本號,此時npm服務器上最新的版本分別為  0.26.1、4.17.21

"dependencies": {
    "axios": "^0.26.0",
    "lodash": "^4.17.20"
  }

package_lock.json文件中的的版本號為 0.26.0 、4.17.20

  "dependencies": {
    "axios": {
      "version": "0.26.0",
      "resolved": "https://registry.npmmirror.com/axios/-/axios-0.26.0.tgz",
      "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==",
      "requires": {
        "follow-redirects": "^1.14.8"
      }
    },
    "lodash": {
      "version": "4.17.20",
      "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.20.tgz",
      "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
    }
  }

運行【npm install】,安裝的是lock中鎖定的版本 0.26.0、4.17.20  (通過查node_modules中下載的源碼可知)

總結:如果copy代碼給別人,只包含package.json文件,則會根據package.json文件的版本號規范,去下載符合規范的最新版本。

          如果包含package.json和package_lock.json文件,且lock的中版本號符合package的規范,則安裝的使lock文件中鎖定的版本號,lock中版本是多少,下載的就是多少。

場景3:存在lock文件,但是安裝指定版本【npm install xxx@1.2.1】

   無論lock中鎖定的版本是多少,都會被修改為1.2.1。

場景4:存在lock文件,安裝默認版本 【npm install xxx】

 如下,package.json文件中axios的版本為 "axios": "^0.26.0",  package_lock.json中的版本號為:0.26.0,服務器上最新的版本號為:0.26.1

 此時運行指令【npm install axios】,結果如下:

 package.json中變為: axios: ^0.26.1,lock文件中的版本號變為:0.26.1

 

三. npm 常用指令

詳見官方文檔:https://docs.npmjs.com/cli-documentation/cli

詳見之前的文檔:https://www.cnblogs.com/yaopengfei/p/14478126.html

 

 

 

四. npx工具

1. 說明

    npx是npm5.2之后自帶的一個命令。npx的作用非常多,但是比較常見的是使用它來調用項目中的某個模塊的指令(node_modules文件夾中的某個包下的指令)。

2. 實操

   比如:以webpack為例,全局安裝的是webpack5.1.3,項目安裝的是webpack3.6.0。

   那么我在項目中的命令行運行指令 【 webpack --version】,顯示的是5.1.3, 調用的是全局的webpack,那么如何調用項目依賴的webpack呢?

方案1:

   直接到node_modules下的webpack文件夾下執行這個指令,如:【./node_modules/.bin/webpack --version】

方案2:

   配置package.json中的script下配置,如下,運行指令【npm run ypf】即可

"scripts": {
    "ypf": "webpack --version"
  },

方案3:

   使用npx直接調用即可,指令為:【npx webpack --version】

五. npm發布包

1. 准備

    首先需要去npm官網注冊npm賬號:https://www.npmjs.com/

2. 發布

   (1). 編寫ESModule代碼

   (2). 項目中運行指令 【npm login】,輸入賬號密碼進行登錄

   (3). 運行指令【npm publish】進行發布

如果要更新的話,需要修改版本號,需要符合semver規范,重新運行【npm publish】進行發布。

其它指令:

    刪除發布的包:【npm unpublish】

    讓發布的包過期:【npm deprecate】

3. 使用

    通過【npm install xxx】下載即可

 

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鵬飛)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 聲     明1 : 如有錯誤,歡迎討論,請勿謾罵^_^。
  • 聲     明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM