20、JS 的依赖管理

109 阅读5分钟

依赖文件:package.json

依赖版本:

"dependencies": {
  "antd": "3.1.2",
  "react": "~16.0.1",
  "redux": "^3.7.2",
  "lodash": "*"
}

"react": "~16.0.1"版本格式:[范围符号]主版本.次版本.修订版本

  • 主版本:不兼容的更改;平时不建议升级
  • 次版本:兼容的功能性新增;平时可以升级
  • 修订版本:兼容的问题修复;平时可以升级

范围符号:

  • *:升级到最新版本
  • ^:升级次版本和修订版本
  • ~:只升级修订版本

因此上述的版本范围为

"dependencies": {
  "antd": "3.1.2", // === 3.1.2
  "react": "~16.0.1", // [16.0.1, 16.1.0)
  "redux": "^3.7.2", // [3.7.2, 4.0.0)
  "lodash": "*" // 永远最新
}

依赖管理工具:npm、yarn、cnpm、pnpm 等

npm:

  • v1:依赖嵌套,依赖的依赖放在各依赖下面,比如下面这样
node_modules
├── A@1.0.0
│   └── node_modules
│       └── B@1.0.0
├── C@1.0.0
│   └── node_modules
│       └── B@2.0.0
└── D@1.0.0
    └── node_modules
        └── B@1.0.0

优点:简单明了
缺点:嵌套太深,重复依赖;
B@1.0.0 存了两份
  • v3:扁平模式,相同的放在根层,冲突的还是放在依赖下面。
node_modules
├── A@1.0.0
├── B@1.0.0
└── C@1.0.0
    └── node_modules
        └── B@2.0.0
├── D@1.0.0

require('A') 时,首先会在当前路径下搜索 node_modules 目录中是否存在该依赖,
如果不存在则往上查找,也就是继续查找该路径的上一层目录下的 node_modules

优点:避免嵌套太深,消除重复依赖
缺点:该版本还缺少 lock 文件,不确定性
什么是确定性?始终得到相同的 node_modules 目录结构
  • v5:node_modules 目录结构跟 v3 一样,但新增了package-lock.json文件,保证依赖的确定性
"dependencies": {
  "redux": "^3.7.2"
}

对应的package-lock.json,记录了每一个依赖的确定版本

{
  "name": "redux",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "redux",
      "version": "1.0.0",
      "license": "ISC",
      "dependencies": {
        "redux": "^3.7.2"
      }
    },
    "node_modules/js-tokens": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
    },
    "node_modules/lodash": {
      "version": "4.17.21",
      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
    },
    "node_modules/lodash-es": {
      "version": "4.17.21",
      "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
      "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
    },
    "node_modules/loose-envify": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
      "dependencies": {
        "js-tokens": "^3.0.0 || ^4.0.0"
      },
      "bin": {
        "loose-envify": "cli.js"
      }
    },
    "node_modules/redux": {
      "version": "3.7.2",
      "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz",
      "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==",
      "dependencies": {
        "lodash": "^4.2.1",
        "lodash-es": "^4.2.1",
        "loose-envify": "^1.1.0",
        "symbol-observable": "^1.0.3"
      }
    },
    "node_modules/symbol-observable": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
      "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==",
      "engines": {
        "node": ">=0.10.0"
      }
    }
  }
}

yarn:

yarn 发布时是为了解决 npm v3 的问题

yarn 生成的 node_modules 目录结构和 npm v5 是相同的,同时默认生成一个 yarn.lock 文件。

特点:yarn.lock 文件里仍然会出现语义化版本范围符号(~^*)

# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"js-tokens@^3.0.0 || ^4.0.0":
  version "4.0.0"
  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
  integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==

lodash-es@^4.2.1:
  version "4.17.21"
  resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
  integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==

lodash@^4.2.1:
  version "4.17.21"
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==

loose-envify@^1.1.0:
  version "1.4.0"
  resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
  integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
  dependencies:
    js-tokens "^3.0.0 || ^4.0.0"

redux@^3.7.2:
  version "3.7.2"
  resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b"
  integrity sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==
  dependencies:
    lodash "^4.2.1"
    lodash-es "^4.2.1"
    loose-envify "^1.1.0"
    symbol-observable "^1.0.3"

symbol-observable@^1.0.3:
  version "1.2.0"
  resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
  integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==

cnpm:

它使用链接 link 的安装方式,提高了安装速度。

它生成的 node_modules 目录采用的是以 版本号 @包名 命名,然后再做软链接到只以包名命名的文件夹上。

优点:按照速度快

缺点:不会生成 lock 文件;生成的 node_modules 目录不一致

pnpm:

使用内容寻址存储来存储依赖包,相同的包(不论被多少个项目所使用)只会在存储中存储一次

它生成的 node_modules 目录如下:直接依赖放在根目录,依赖的依赖放在 .pnpm 文件夹内

默认生成一个 pnpm-lock.yaml 文件。

lockfileVersion: 5.4

specifiers:
  redux: ^3.7.2

dependencies:
  redux: 3.7.2

packages:

  /js-tokens/4.0.0:
    resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
    dev: false

  /lodash-es/4.17.21:
    resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
    dev: false

  /lodash/4.17.21:
    resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
    dev: false

  /loose-envify/1.4.0:
    resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
    hasBin: true
    dependencies:
      js-tokens: 4.0.0
    dev: false

  /redux/3.7.2:
    resolution: {integrity: sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==}
    dependencies:
      lodash: 4.17.21
      lodash-es: 4.17.21
      loose-envify: 1.4.0
      symbol-observable: 1.2.0
    dev: false

  /symbol-observable/1.2.0:
    resolution: {integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==}
    engines: {node: '>=0.10.0'}
    dev: false

循环依赖:

A 依赖 B,B 依赖 A

幽灵依赖:

项目中用了的包,但未在 package.json 中定义。

这是因为依赖提升造成的副作用