Skip to content

原文:新一代包管理工具 pnpm 使用心得

关于现代包管理器的深度思考——为什么现在我更推荐 pnpm 而不是 npm/yarn?

pnpm 文档

****

<font style="color:rgb(18, 18, 18);">npm create vite@latest my-vue-app -- --template vue</font>

javascript
{
  "name": "my-vue-app",
  "private": true,
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
-   "vue": "^3.2.25"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^2.3.3",
    "vite": "^2.9.9"
+   "vue": "^3.2.25"
  }
}

<font style="color:rgb(18, 18, 18);">npm i npm </font>

<font style="color:rgb(18, 18, 18);">run build </font>

<font style="color:rgb(18, 18, 18);">npm run preview</font>

********

javascript
{
  "name": "a",
  "dependencies": {
    "b": "^1.0.0"
  },
  "devDependencies": {
    "c": "^1.0.0"
  }
}
javascript
// node_modules/b/package.json
{
  "name": "b",
  "dependencies": {
    "d": "^1.0.0"
  },
  "devDependencies": {
    "e": "^1.0.0"
  }
}
// node_modules/c/package.json
{
  "name": "c",
  "dependencies": {
    "f": "^1.0.0"
  },
  "devDependencies": {
    "g": "^1.0.0"
  }
}

javascript
node_modules
├── b       // a 的 dependencies
├── c       // a 的 devDependencies   
├── d       // b 的 dependencies    
└── f       // c 的 dependencies
[传统包管理器的文件结构](https://zhuanlan.zhihu.com/p/546400909/edit#%E4%BC%A0%E7%BB%9F%E5%8C%85%E7%AE%A1%E7%90%86%E5%99%A8%E7%9A%84%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84)****

javascript
// @vitejs/plugin-vue2 的 package.json
{
  "name": "@vitejs/plugin-vue2",
  // ...
  "peerDependencies": {
    "vite": ">=2.5.10",
    "vue": "^2.7.0-0"
  },
  // dependencies、devDependencies 与其他字段 ...
}

[dependencies 和 devDependencies 的区别](https://zhuanlan.zhihu.com/p/546400909/edit#dependencies-%E5%92%8C-devdependencies-%E7%9A%84%E5%8C%BA%E5%88%AB)

javascript
node_modules
├── b                 // a 的 dependencies
|   └── node_modules
|       └── d         // b 的 dependencies 
├── c                 // a 的 devDependencies
|   └── node_modules
|       └── f         // c 的 dependencies
javascript
node_modules
├── b       // a 的 dependencies
├── c       // a 的 devDependencies   
├── d       // b 的 dependencies    
└── f       // c 的 dependencies
  • ************

3、pnpm的优势

[关于现代包管理器的深度思考——为什么现在我更推荐 pnpm 而不是 npm/yarn?](https://link.zhihu.com/?target=https%3A//juejin.cn/post/6932046455733485575)****[Linux软连接和硬链接](https://link.zhihu.com/?target=https%3A//www.cnblogs.com/itech/archive/2009/04/10/1433052.html)

<font style="color:rgb(18, 18, 18);">npm i vue -S</font>

<font style="color:rgb(18, 18, 18);">pnpm i vue -S</font>

[上一节](https://zhuanlan.zhihu.com/p/546400909/edit#pnpm-%E4%BC%98%E5%8A%BF-%E8%BD%AF%E9%93%BE%E6%8E%A5%E4%BC%98%E5%8C%96%E4%BE%9D%E8%B5%96%E7%AE%A1%E7%90%86)

************************

****.npmrc | 依赖提升设置

[官方文档](https://link.zhihu.com/?target=https%3A//pnpm.io/zh/cli/install)
javascript
{
  // ...
  "dependencies": {
    "axios": "^0.21.0",
    "cropperjs": "^1.5.11",
    "echarts": "^4.8.0",
    "echarts-liquidfill": "^2.0.6",
    "element-ui": "^2.13.2",
    "file-saver": "^2.0.5",
    "highlight.js": "^9.0.0",
    "js-base64": "^3.7.2",
    "lodash": "^4.17.19",
    "marked": "^1.2.7",
    "moment": "^2.24.0",
    "qs": "^6.10.2",
    "save": "^2.4.0",
    "sortablejs": "^1.13.0",
    "v-viewer": "^1.5.1",
    "video.js": "^7.10.2",
    "vue": "^2.6.11",
    "vue-bus": "^1.2.1",
    "vue-clipboard2": "^0.3.1",
    "vue-contextmenu": "^1.5.10",
    "vue-cropper": "^0.5.5",
    "vue-py": "0.0.4",
    "vue-qr": "^4.0.9",
    "vue-router": "^3.4.3",
    "vue-ueditor-wrap": "^2.4.4",
    "vuedraggable": "^2.24.3",
    "vuex": "^3.4.0",
    "xlsx": "^0.16.9",
    "xss": "^1.0.10"
  },
  "devDependencies": {
    "@types/echarts": "^4.9.12",
    "@types/file-saver": "^2.0.4",
    "@types/lodash": "^4.14.178",
    "@types/node": "^17.0.16",
    "@types/qs": "^6.9.7",
    "@types/sortablejs": "^1.10.7",
    "@typescript-eslint/eslint-plugin": "^5.10.1",
    "@typescript-eslint/parser": "^5.11.0",
    "@vitejs/plugin-legacy": "^1.7.1",
    "cross-env": "^7.0.3",
    "eslint": "^7.32.0",
    "eslint-config-airbnb-base": "^15.0.0",
    "eslint-config-airbnb-typescript": "^16.1.0",
    "eslint-plugin-vue": "^8.4.0",
    "prettier": "^1.18.2",
    "sass": "~1.32.13",
    "stylelint": "^14.3.0",
    "stylelint-config-recess-order": "^3.0.0",
    "stylelint-config-recommended-vue": "^1.1.0",
    "stylelint-config-standard-scss": "^3.0.0",
    "typescript": "^4.4.4",
    "vite": "^2.8.6",
    "vite-plugin-html-env": "^1.1.1",
    "vite-plugin-vue2": "^1.9.3",
    "vue-eslint-parser": "^8.2.0",
    "vue-template-compiler": "^2.6.11",
    "vue-tsc": "^0.31.1"
  },
  // ...
}
javascript
# 根据 package.json 中的依赖声明安装全部依赖
pnpm install
# 安装指定依赖,并在 dependencies 中声明依赖
pnpm install -S xxx
# 安装指定依赖,并在 devDependencies 中声明依赖
pnpm install -D xxx
# 卸载指定依赖
pnpm uninstall xxx
javascript
ERR_PNPM_PEER_DEP_ISSUES  Unmet peer dependencies

.
├─┬ eslint-config-airbnb-base
│ └── ✕ missing peer eslint-plugin-import@^2.25.2
├─┬ eslint-config-airbnb-typescript
│ └── ✕ missing peer eslint-plugin-import@^2.25.3
├─┬ stylelint-config-recommended-vue
│ ├── ✕ missing peer postcss-html@^1.0.0
│ └─┬ stylelint-config-html
│   └── ✕ missing peer postcss-html@^1.0.0
├─┬ stylelint-config-standard-scss
│ └─┬ stylelint-config-recommended-scss
│   └─┬ postcss-scss
│     └── ✕ missing peer postcss@^8.3.3
└─┬ echarts-liquidfill
  └── ✕ missing peer zrender@^4.3.1
Peer dependencies that should be installed:
  eslint-plugin-import@">=2.25.3 <3.0.0"  postcss-html@">=1.0.0 <2.0.0"           postcss@^8.3.3                          zrender@^4.3.1
javascript
pnpm i -D eslint-plugin-import postcss-html postcss
pnpm i -S zrender@^4.3.1

<font style="color:rgb(18, 18, 18);">pnpm run dev</font>

javascript
// node_modules/v-viewer/package.json
{
  "name": "v-viewer",
  // ...
  "dependencies": {
    "throttle-debounce": "^2.0.1",
    "viewerjs": "^1.5.0"
  }
}
[传统包管理器的文件结构](https://zhuanlan.zhihu.com/p/546400909/edit#%E4%BC%A0%E7%BB%9F%E5%8C%85%E7%AE%A1%E7%90%86%E5%99%A8%E7%9A%84%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84)

<font style="color:rgb(18, 18, 18);">pnpm i -S viewerjs</font>

依赖提升设置
javascript
# .npmrc
# 提升含有 eslint(模糊匹配)、prettier(模糊匹配)、viewerjs(精确匹配) 的依赖包到根 node_modules 目录下
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=viewerjs

# 提升所有依赖到根 node_modules 目录下,相当于 public-hoist-pattern[]=*,与上面一种方式一般二选一使用
shamefully-hoist=true
****[FAQ](https://link.zhihu.com/?target=https%3A//pnpm.io/zh/faq%23pnpm-%25E6%2597%25A0%25E6%25B3%2595%25E5%259C%25A8-%25E4%25BD%25A0%25E7%259A%2584%25E9%25A1%25B9%25E7%259B%25AE%25E4%25B8%25AD%25E4%25BD%25BF%25E7%2594%25A8-)